using BaseOUDAL; using Qdp.Foundation.Implementations; using System.Text.RegularExpressions; using YLErp.Abstract.DataProviders; using YLErp.Commons; using YLErp.DBModels.Consts; using YLErp.Model; using YLErp.Modules.DataProviderModule; using YLErp.Modules.SuperviseReportModule.CFMMC2022.Model; using YLErp.Modules.TradeModule; using YLErp.QdpModule; using static YLErp.Modules.SuperviseReportModule.CFMMC2022.Model.SuperviseReportBaseModel; namespace YLErp.Modules.SuperviseReportModule.CFMMC2022.Service { public abstract class SuperviseReportBaseService : YLBaseService { protected SuperviseReportReq _req { get; set; } /// /// 分隔符 /// 分号 /// protected string _separator => ";"; protected IEodPriceProviderWrap _priceProvider; protected SuperviseReportBaseService(SuperviseReportReq req, OptUserInfo userInfo) : base(userInfo) { _req = req ?? throw new ArgumentNullException(nameof(req)); _priceProvider = new EodPriceProvider(_req.ValueDate).GetPriceProvider(SettlementTypeEnum.ClosePrice); } private readonly List ignoreTradeTypes = new List() { "区间累积期权" }; /// /// 了结交易类型代码集合 /// private readonly List tradeTypes = new List() { "PU", "FU", "ED" }; /// /// /// /// /// 标的资产类型 /// 资产类型 /// 标的资产品种后缀和标的资产对应合约后缀 /// 组合标的价格 /// EodTrade不存在时抛出 protected virtual void FormatModel(SuperviseReportBaseModel model, List assetTypes, List varietySuffixs, List varietyCodeList, out SyntheticPriceModel syntheticPrice) { if (model.trade == null) { throw new ServiceException($"日终Trade不存在,交易编号:{model.OriginalTradeNumber}"); } //工具类型 model.ToolType = formatToolType(model.trade.TradeType, model.StructureType); //当“工具类型”为OP或FW时,该字段只能填报B或S if (model.ToolType == "OP") { model.ClientDirection = model.trade.BuySell == "买入" ? "B" : "S"; } else if (model.ToolType == "FW") { model.ClientDirection = (model.trade.BuySell == "买入" && model.trade.OptionType == "看涨") || (model.trade.BuySell == "卖出" && model.trade.OptionType == "看跌") ? "B" : "S"; } //当“工具类型“为SW时,该字段只能填报P或R else if (model.ToolType == "SW") { model.ClientDirection = model.trade.trade_swap.IsGetFloatingProfit ? "P" : "R"; } //期初价格 model.UnderlyingInitialPrice = model.trade.SpotPrice.OtcFormatFlex(2); //formatTradeAmount(model.trade.SpotPrice); var um = DataCacheProvider.GetUnderlyingDataSource().GetData(model.trade.UnderlyingCode); if (um.IsSynthetic() || !string.IsNullOrWhiteSpace(model.trade.BasisUnderlyingCode)) { var marketNoDict = new Dictionary(); var query = DbContext.TradeMeta.Where(O => O.TradeId == model.trade.id && O.MetaValue.Length > 5); if (um.IsSynthetic()) { query = query.Where(O => O.MetaKey.StartsWith(ConsTradeMetaKey.SyntheticUnderlying)); var tradeMeta = query.FirstOrDefault(); if (string.IsNullOrWhiteSpace(tradeMeta?.MetaValue)) { throw new ServiceException($"组合标的期初价格信息不完整,交易编号:{model.OriginalTradeNumber}"); } syntheticPrice = JsonHelper.Deserialize(tradeMeta.MetaValue); if (syntheticPrice.SuList == null) { throw new ServiceException($"组合标的价格缺失,交易编号:{model.trade.TradeNumber}"); } } else { query = query.Where(O => O.MetaKey == ConsTradeMetaKey.SpotInfos); var tradeMeta = query.FirstOrDefault(); string[] arrPrice = null; if (string.IsNullOrWhiteSpace(tradeMeta?.MetaValue)) { arrPrice = new[] { model.trade.SpotPrice?.ToString() }; } else { arrPrice = JsonHelper.Deserialize(tradeMeta.MetaValue); if (arrPrice == null || arrPrice.Length == 0) { throw new ServiceException($"期初价格缺失,交易编号:{model.trade.TradeNumber}"); } } var prides = new UnderlyingPriceModel[arrPrice.Length]; for (var i = 0; i < arrPrice.Length; i++) { prides[i] = new UnderlyingPriceModel { Price = double.TryParse(arrPrice[i], out var p) ? p : 0, Coefficient = i == 0 ? 1 : -1, UnderlyingCode = i == 0 ? model.trade.UnderlyingCode : model.trade.BasisUnderlyingCode }; } syntheticPrice = new SyntheticPriceModel { SuList = prides }; } var underlyingCodes = syntheticPrice.SuList.Select(O => O).ToArray(); var arrCode = new string[underlyingCodes.Length]; var arrUnitZh = new string[underlyingCodes.Length]; var arrUnitEn = new string[underlyingCodes.Length]; var arrVarietyType = new string[underlyingCodes.Length]; var arrUnderlyingPlate = new string[underlyingCodes.Length]; var arrDeltaCash = new string[underlyingCodes.Length]; //多表的资产类型 var vTypeIsOther = false; var vTypeStr = ""; //多标的数量单位 var vUnitEnIsOther = false; var vUnitEnStr = ""; for (var i = 0; i < underlyingCodes.Length; i++) { if (underlyingCodes[i] == null || string.IsNullOrWhiteSpace(underlyingCodes[i].UnderlyingCode)) { arrCode[i] = null; arrUnitZh[i] = null; arrUnitEn[i] = null; arrVarietyType[i] = null; continue; } var variety = UnderlyingDataProvider.GetVariety(underlyingCodes[i].UnderlyingCode); if (variety == null) { throw new ServiceException($"未找到品种数据: {underlyingCodes[i].UnderlyingCode}"); } var um1 = UnderlyingDataProvider.GetUnderlying(underlyingCodes[i].UnderlyingCode); var varietySuffix = formatDictItem(varietySuffixs, um1?.MarketCode, um1?.MarketCode); marketNoDict[underlyingCodes[i].UnderlyingCode] = varietySuffix; arrCode[i] = formatVarietyCode(underlyingCodes[i].UnderlyingCode, variety, varietyCodeList, varietySuffix); arrUnitZh[i] = um?.QuoteUnit;//variety.QuoteUnitSingleOriginal; //arrUnitEn[i] = formatQuoteUnit(arrUnitZh[i]); //arrVarietyType[i] = formatVariety(variety.MainCategory); arrUnderlyingPlate[i] = formatUnderlyingPlate(variety.AssetType); arrDeltaCash[i] = OtcFormatHelper.FormatValue((model._delta * underlyingCodes[i].Price), 4).ToString(); //多标的数量单位,如果不同的数量单位,就报其他(O) if (string.IsNullOrEmpty(vUnitEnStr)) { vUnitEnStr = arrUnderlyingPlate[i] == "IN" ? "元/指数点" : formatQuoteUnit(arrUnitZh[i]); } else { if (vUnitEnStr != (arrUnderlyingPlate[i] == "IN" ? "元/指数点" : formatQuoteUnit(arrUnitZh[i]))) { vUnitEnIsOther = true; } } //多标的资产类型,如果不同的资产类型,就报其他(O) if (string.IsNullOrEmpty(vTypeStr)) { vTypeStr = formatVariety(variety.MainCategory); } else { if (vTypeStr != formatVariety(variety.MainCategory)) { vTypeIsOther = true; } } } model.UnderlyingCode = formatSyntheticUnderlying(syntheticPrice, marketNoDict); model.VarietyCode = JoinArr(arrCode); //model.QuoteUnitEn = JoinArr(arrUnitEn); model.QuoteUnitEn = vUnitEnIsOther ? "Other" : vUnitEnStr; //model.VarietyType = JoinArr(arrVarietyType); model.VarietyType = vTypeIsOther ? "O" : vTypeStr; model.UnderlyingPlate = JoinArr(arrUnderlyingPlate); model.DeltaCash = JoinArr(arrDeltaCash); } else { var variety = UnderlyingDataProvider.GetVariety(model.trade.UnderlyingCode); if (variety == null) { throw new ServiceException($"未找到品种数据: {model.trade.UnderlyingCode}"); } var varietySuffix = formatDictItem(varietySuffixs, um?.MarketCode, um?.MarketCode); model.UnderlyingCode = formatUnderlyingCode(model.trade.UnderlyingCode, varietySuffix); model.VarietyCode = formatVarietyCode(model.trade.UnderlyingCode, variety, varietyCodeList, varietySuffix); model.VarietyType = formatVariety(variety.MainCategory); model.UnderlyingPlate = formatUnderlyingPlate(variety.AssetType); model.QuoteUnitEn = model.UnderlyingPlate == "IN" ? "元/指数点" : formatQuoteUnit(um?.QuoteUnit); model.DeltaCash = OtcFormatHelper.FormatValue((model._delta * model._price ?? model.trade.SpotPrice), 4).ToString(); syntheticPrice = null; } if (um?.UnderlyingInstrumentType == "Stock") { model.IsStock = true; } model.UnderlyingInitialPriceSymbol = formatPriceSymbol(model.UnderlyingPlate); if (model.UnderlyingInitialPriceSymbol == "1") { model.UnderlyingInitialPriceCurrency = "CNY"; } //期权行权时间类型 model.ExerciseMode = IsOption(model.trade) && model.trade.TradeType != "自定义交易" ? (model.trade.ExerciseMode == "European" ? "EU" : "US") : "O"; //国投特殊处理 model.ExerciseMode = PS.Config.Company == Configuration.CompanyEnum.国投 && model.trade.TradeType == "雪球期权" ? "O" : model.ExerciseMode; model.OptionType = ignoreTradeTypes.Contains(model.trade.TradeType) ? "9" : IsOption(model.trade) ? (model.trade.OptionType == "看涨" ? "2" : "1") : "9"; if (model.ToolType == "FW" || model.ToolType == "SW") { model.ExerciseMode = null; model.OptionType = null; } //看跌是1,看涨是2,价差是9 if (model.trade.TradeType == "凤凰期权") { if (model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToPutOption || model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption) { model.OptionType = "1"; } else if (model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToCallOption || model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption) { model.OptionType = "2"; } else { model.OptionType = "9"; } } else if (model.trade.TradeType == "雪球期权") { if (model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToPutOption || model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption) { model.OptionType = "1"; } else if (model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToCallOption || model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption) { model.OptionType = "2"; } else { model.OptionType = "9"; } } //多腿编号 model.MoreLegCode = formatTradeNumber(model); //期权产品结构 model.OptionProductStructure = formatOptionProductStructure(model); //获取执行价格 formatStrike(model); //观察类型、观察起始日、观察截止日、观察周期、观察周期乘数 formatObserveType(model); //收益计算方式 formatRevenueCalculationMethod(model); //保底收益 model.GuaranteedIncome = model.trade.OriginalPrincipalSum * (model.trade.Notional / model.trade.OriginalNotional); model.GuaranteedIncomeSymbol = "1"; model.GuaranteedIncomeCurrency = "CNY"; //保底收益率 if (model.trade.IsUsePremiumRate == true) { model.GuaranteedIncome = model.trade.PrincipalRateWrite; model.GuaranteedIncomeCurrency = null; model.GuaranteedIncomeSymbol = "2"; } //参与率 model.ParticipateRate = model.trade.ParticipationRate ?? 1; //是否为年化名义金额 model.IsAnnualizedNominalAmount = model.trade.IsAnnualized ? "Y" : "N"; //凤凰、雪球 if (model.OptionProductStructure == "PA") { model.IsAnnualizedNominalAmount = model.trade.trade_autocall.IsAnnualized2 ? "Y" : "N"; } else if (model.OptionProductStructure == "SA" || model.OptionProductStructure == "GSA") { model.IsAnnualizedNominalAmount = model.trade.trade_snowball.IsAnnualized2 ? "Y" : "N"; //小雪球的时候,红利票息赋值给保底收益 if (model.OptionProductStructure == "GSA") { model.GuaranteedIncome = model.trade.trade_snowball.Coupon; model.GuaranteedIncomeCurrency = null; model.GuaranteedIncomeSymbol = "2"; } } //特定字段赋值 switch (model.ToolType) { case "OP": setOptionlFields(model); break; case "FW": setForwardFields(model); break; case "SW": setSwapFields(model); break; } //自定义字段结构不为空时,处理自定义字段报送 if (!string.IsNullOrEmpty(model.ExtendInfo)) { formatExtendInfo(model); } } /// /// 获取资产类型 /// /// /// private string formatVariety(string inputVal) { var varietyType = ""; switch (inputVal) { case "Equity": varietyType = "EQ"; break; case "BulkCommodity": varietyType = "CO"; break; case "InterestRate": varietyType = "IR"; break; case "Credit": varietyType = "CR"; break; case "ExchangeRate": varietyType = "FX"; break; default: varietyType = "CO"; break; } return varietyType; } /// /// 获取价格符号 /// /// /// private string formatPriceSymbol(string underlyingPlate) { switch (underlyingPlate) { case "IN": return "3"; case "LIBOR": case "LPR": case "GBOND": case "TBOND": case "PolicyBBOND": case "CBOND": case "FBOND": return "2"; default: return "1"; } } protected double formatInitCastClientPayable(trade t) { double result = 0; if (t != null) { result = (t.InitialMargin * (t.Notional / t.OriginalNotional)) ?? 0; } return Math.Max(0, result); } protected string formatTradeAmount(double? notional, double coefficient = 1) { var value = notional * coefficient; return OtcFormatHelper.FormatValue(value, 4).ToString(); } /// /// 获取工具类型 /// /// /// /// private string formatToolType(string tradeType, string structureType) { var toolType = "O"; switch (tradeType) { case "收益互换": toolType = "SW"; break; case "远期": toolType = "FW"; if (structureType == "掉期") { toolType = "SW"; } break; default: toolType = "OP"; break; } return toolType; } protected string formatDictItem(List dictItemMap, string name, string defaultValue = "") { if (name == null || dictItemMap == null) { return defaultValue; } var obj = dictItemMap.FirstOrDefault(O => O.Name == name); return obj == null ? defaultValue : obj.ShortName; } private string formatSyntheticUnderlying(SyntheticPriceModel underlying, Dictionary exchangeNo) { Func formatCode = (_coefficient, _underlyingCode) => { var code = formatUnderlyingCode(_underlyingCode, exchangeNo[_underlyingCode]); var coef = Math.Abs(_coefficient).ToString(); return $"{(coef == "1" ? null : coef)}{code}"; }; var tipsInfo = ""; foreach (var item in underlying.SuList) { if (!string.IsNullOrEmpty(tipsInfo) || item.Coefficient < 0) { tipsInfo += (item.Coefficient >= 0 ? "+" : "-"); } tipsInfo += formatCode(item.Coefficient, item.UnderlyingCode); } return tipsInfo; } /// /// 获取标的代码 /// /// /// /// /// private string formatUnderlyingCode(string underlyingCode, string exchangeNo) { if (string.IsNullOrWhiteSpace(underlyingCode)) { throw new ArgumentException("标的代码不存在", nameof(underlyingCode)); } var superviseUndelrying = DbContext.supervise_undelrying.FirstOrDefault(n => n.undelrying == underlyingCode); if (superviseUndelrying != null && !string.IsNullOrEmpty(superviseUndelrying.undelrying_CFMMC)) { return superviseUndelrying.undelrying_CFMMC; } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (underlying == null) { throw new ArgumentException("标的信息不存在:" + underlyingCode); } if (underlying.UnderlyingInstrumentType == ConsGlobal.InstrumentType.CommoditySpot) { return underlying.UnderlyingName; } else if (underlyingCode.Contains(".")) { return underlyingCode; } return $"{underlyingCode}.{exchangeNo}"; } /// /// 获取标的资产所属板块 /// /// /// private string formatUnderlyingPlate(string inputVal) { switch (inputVal) { case "贵金属": case "有色及贵金属": return "Pmetal"; case "黑色": return "Ferrous"; case "能化": case "能源化工": return "ECH"; case "农产品": return "AGP"; case "有色": return "NonFerrous"; case "商品ETF": return "COETF"; case "个股": return "SK"; case "股指": case "指数": return "IN"; case "基金": return "FD"; case "LIBOR": return "LIBOR"; case "LPR": return "LPR"; case "地方政府债": return "GBOND"; case "国股银票转贴现": return "BAEX_1"; case "国债": return "TBOND"; case "政策性金融债": return "PolicyBBOND"; case "美元兑人民币": return "USDRMB"; case "公司债": return "CBOND"; case "金融债": return "FBOND"; default: return null; } } /// /// 多腿编号 /// /// /// private string formatTradeNumber(SuperviseReportBaseModel model) { var tradeNum = ""; if (model.ParentTradeId > 0) { if (PS.Config.Company == Configuration.CompanyEnum.浙期) { if (!int.TryParse(Regex.Match(model.OriginalTradeNumber ?? "", @"(?<=X)\d+$").Value, out var tradeNum2)) { return null; } tradeNum = tradeNum2.ToString(); } else if (PS.Config.Is物产中大 && model.ParentTradeId > 0) { tradeNum = (DbContext.trade.Where(l=>l.id 0) { var arrOTNum = model.OriginalTradeNumber.Split('-'); tradeNum = arrOTNum[arrOTNum.Length - 1]; } } else { tradeNum = null; } return tradeNum; } /// /// 获取期权产品结构 /// /// /// private string formatOptionProductStructure(SuperviseReportBaseModel model) { var tradeTypeEn = "O"; switch (model.OptionProductStructure) { case "香草期权": tradeTypeEn = "VA"; break; case "亚式期权": tradeTypeEn = "AS"; break; case "二元期权": tradeTypeEn = "DI"; break; case "区间累计期权": case "区间累积期权": tradeTypeEn = "RA"; break; case "障碍期权": if (model.trade.trade_barrier_option.BarrierType.StartsWith("双障碍")) { tradeTypeEn = "DSF"; } else if (model.trade.trade_barrier_option.BarrierType.EndsWith("敲入")) { tradeTypeEn = "SKI"; } else if (model.trade.trade_barrier_option.BarrierType.EndsWith("敲出")) { tradeTypeEn = "SF"; } break; case "双鲨期权": tradeTypeEn = "DSF"; break; case "累计期权": tradeTypeEn = "AC"; break; case "雪球期权": if (model.trade.trade_snowball.KIPayoffType == 0) { tradeTypeEn = "GSA"; } else { tradeTypeEn = "SA"; } break; case "凤凰期权": tradeTypeEn = "PA"; break; case "自定义交易": tradeTypeEn = "O"; if (!string.IsNullOrEmpty(model.trade.StructureType)) { var customTradeInfo = DbContext.Structure_Info.FirstOrDefault(n => n.StructureName == model.trade.StructureType); if (customTradeInfo != null) { if (!string.IsNullOrEmpty(customTradeInfo.StructureTypeSm)) { tradeTypeEn = customTradeInfo.StructureTypeSm; } } } break; default: tradeTypeEn = "O"; break; } return tradeTypeEn; } /// /// 获取标的资产品种 /// /// /// /// /// /// /// private string formatVarietyCode(string underlyingCode, Variety variety, List varietyCodeList, string marketExchangeNo) { if (string.IsNullOrWhiteSpace(underlyingCode)) { throw new ArgumentException("标的代码不存在", nameof(underlyingCode)); } var code = varietyCodeList.Where(O => O.Name.ToLower() == underlyingCode.ToLower()).Select(O => O.ShortName).FirstOrDefault(); if (!string.IsNullOrEmpty(code)) { return code; } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (underlying == null) { throw new ArgumentException("标的信息不存在:" + underlyingCode); } var assetVariety = $"{{0}}.{marketExchangeNo}"; switch (underlying.UnderlyingInstrumentType) { case ConsGlobal.InstrumentType.StockIndex: case ConsGlobal.InstrumentType.StockIF: assetVariety = variety.VarietyName; break; case ConsGlobal.InstrumentType.CommodityFutures: assetVariety = string.Format(assetVariety, variety.VarietyCode); break; case ConsGlobal.InstrumentType.CommoditySpot: if (marketExchangeNo == "SGE") { assetVariety = string.Format(assetVariety, underlyingCode); } else { assetVariety = variety.VarietyName; } break; case ConsGlobal.InstrumentType.Stock: //assetVariety = string.Format(assetVariety, getStockVarietyCode(underlyingCode)); assetVariety = getStockVarietyCode(underlyingCode); break; default: assetVariety = underlyingCode; break; } return assetVariety; } private string getStockVarietyCode(string code) { var assetVariety = ""; if (code.StartsWith("60") || code.StartsWith("000")) { //主板 assetVariety = "ZB"; } else if (code.StartsWith("002")) {//中小板 //assetVariety = "ZXB"; assetVariety = "ZB"; } else if (code.StartsWith("300")) {//创业板 assetVariety = "CYB"; } else if (code.StartsWith("688")) {//科创版 assetVariety = "KCB"; } else { assetVariety = ""; } return assetVariety; } /// /// 获取数量单位 /// /// /// private string formatQuoteUnit(string quoteUnit) { switch (quoteUnit) { case "吨": return "t"; case "桶": return "barrel"; case "克": return "g"; case "千克": return "kg"; case "500千克": return "500kg"; case "股": case "股(份)": return "share"; case "磅": return "lb"; case "点": //if (PS.Config.Company == Configuration.CompanyEnum.国投) //{ // return "bp"; //} //return "point"; case "基点": //return "bp"; case "units": //return "units"; return "Other"; case "指数": case "元/指数点": return "元/指数点"; default: return "Other"; } //return quoteUnit; } protected double formatEndStockEqvNotionalReal(double? stockEqvNotional, double percentRate) { var result = stockEqvNotional * percentRate; return Math.Abs(OtcFormatHelper.FormatValue((result ?? 0), 4)); } protected string JoinArr(string[] arr) { var singleArr = new HashSet(arr); singleArr.Remove(""); return string.Join(";", singleArr); } /// /// 是否为期权 /// /// /// private bool IsOption(trade t) { return t.IsOption() || t.TradeType == "自定义交易"; } /// /// 获取执行价格1、2、3 /// /// /// private void formatStrike(SuperviseReportBaseModel model) { //执行价格符号 model.StrikeSymbol = formatPriceSymbol(model.UnderlyingPlate); if (model.StrikeSymbol == "1") { //执行价格货币 model.StrikeCurrency = "CNY"; } var trade = model.trade; //当期权产品结构为 AS(亚式期权),且执行价为观察期内标的价格的均值,则此处无需填写执行价格 if (model.OptionProductStructure == "AS" && trade.trade_asian_option.StrikeType == "Floating") { return; } //执行价1 model.Strike = trade.Strike ?? 0; //trade.IsMoneynessOption == "是" ? ((trade.Strike * trade.SpotPrice) ?? 0) : if (trade.IsMoneynessOption == "是") { model.Strike = ((trade.Strike * trade.SpotPrice) ?? 0); } //执行价2 if (model.OptionProductStructure == "SA" || model.OptionProductStructure == "GSA") { model.Strike2 = trade.trade_snowball.SpreadStrikeAtMaturity; if (trade.IsMoneynessOption == "是") { model.Strike2 = (trade.trade_snowball.SpreadStrikeAtMaturity * trade.SpotPrice); } } else if (model.OptionProductStructure == "PA") { model.Strike2 = trade.trade_autocall.SpreadStrike; if (trade.IsMoneynessOption == "是") { model.Strike2 = (trade.trade_autocall.SpreadStrike * trade.SpotPrice); } } else if (model.OptionProductStructure == "DI" && trade.trade_binary_option.PayoffType.StartsWith("Double")) { model.Strike2 = trade.trade_binary_option.UpperBarrier; if (trade.IsMoneynessOption == "是") { model.Strike2 = (trade.trade_binary_option.UpperBarrier * trade.SpotPrice); } } else if (model.OptionProductStructure == "O" && trade.trade_risky_option != null) { model.Strike2 = trade.trade_risky_option.Strike2; model.Strike3 = trade.trade_risky_option.Strike3; if (trade.IsMoneynessOption == "是") { model.Strike2 = (trade.trade_risky_option.Strike2 * trade.SpotPrice); model.Strike3 = (trade.trade_risky_option.Strike3 * trade.SpotPrice); } } else if (model.OptionProductStructure == "AC" && trade.trade_accumulator_option != null && trade.trade_accumulator_option.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) { model.Strike2 = trade.trade_accumulator_option.Strike2; model.Strike3 = trade.trade_accumulator_option.Strike3; if (trade.IsMoneynessOption == "是") { model.Strike2 = (trade.trade_accumulator_option.Strike2 * trade.SpotPrice); model.Strike3 = (trade.trade_accumulator_option.Strike3 * trade.SpotPrice); } } if (model.Strike > model.Strike2 && model.Strike2 > 0) { var tempVal = model.Strike2 ?? 0; model.Strike2 = model.Strike; model.Strike = tempVal; } } /// /// 获取观察方式、观察开始时间、观察结束时间、观察周期 /// /// /// private void formatObserveType(SuperviseReportBaseModel model) { string getObType(string input) { switch (input) { case "离散": return "DISCRETE"; case "连续": return "CONTINUOUS"; case "到期": return "TERMINAL"; default: return "DISCRETE"; } } DateTime getObSDate(string observationDates, out DateTime inputDateTime) { var observations = observationDates.Split(','); var observeStartData = DateTime.Parse(observations[0]); inputDateTime = DateTime.Parse(observations[(observations.Count() - 1)]); return observeStartData; } var trade = model.trade; DateTime oSd; DateTime observeEndDate; switch (model.OptionProductStructure) { case "AS": model.ObserveType = getObType("离散"); model.ObserveStartDate = trade.trade_asian_option?.AveragingPeriodStartDate; model.ObserveEndDate = model.EndDate; break; case "DI": model.ObserveType = getObType((trade.ExerciseModeCn == "欧式" || trade.ExerciseMode == "European") ? "到期" : trade.trade_binary_option.MonitorType); if (!string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates)) { model.ObserveStartDate = getObSDate(trade.trade_binary_option.ObservationDates, out observeEndDate); model.ObserveEndDate = observeEndDate; } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } break; case "RA": model.ObserveType = getObType("离散");//trade_rangeaccrual if (!string.IsNullOrEmpty(trade.trade_rangeaccrual.ObservationDates)) { model.ObserveStartDate = getObSDate(trade.trade_rangeaccrual.ObservationDates, out observeEndDate); model.ObserveEndDate = observeEndDate; if (isTerminal(trade.trade_rangeaccrual.ObservationDates, model.EndDate.Value)) { model.ObserveType = "TERMINAL"; } } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } break; case "SF": case "SKI": model.ObserveType = getObType(trade.trade_barrier_option.Discrete); if (!string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates)) { model.ObserveStartDate = getObSDate(trade.trade_barrier_option.ObservationDates, out observeEndDate); model.ObserveEndDate = observeEndDate; } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } break; case "DSF": if (model.ProductType == "双鲨期权") { model.ObserveType = getObType(trade.trade_double_sharkfin_option.Discrete); if (!string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates)) { model.ObserveStartDate = getObSDate(trade.trade_double_sharkfin_option.ObservationDates, out observeEndDate); model.ObserveEndDate = observeEndDate; } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } } else { model.ObserveType = getObType(trade.trade_barrier_option.Discrete); if (!string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates)) { model.ObserveStartDate = getObSDate(trade.trade_barrier_option.ObservationDates, out observeEndDate); model.ObserveEndDate = observeEndDate; } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } } break; case "AC": model.ObserveType = getObType("离散");//trade_accumulator_option if (!string.IsNullOrEmpty(trade.trade_accumulator_option.KOObservationDates)) { var KOObservationDatesArr = trade.trade_accumulator_option.KOObservationDates.Split(';'); if (KOObservationDatesArr.Length > 0) { model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate); model.ObserveEndDate = observeEndDate; if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value)) { model.ObserveType = "TERMINAL"; } } } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } break; case "SA": case "GSA": model.ObserveType = getObType("离散");//trade_snowball if (!string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates)) { var KOObservationDatesArr = trade.trade_snowball.KOObservationDates.Split(';'); if (KOObservationDatesArr.Length > 0) { model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate); model.ObserveEndDate = observeEndDate; if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value)) { model.ObserveType = "TERMINAL"; } } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } } break; case "PA": model.ObserveType = getObType("离散");//trade_autocall if (!string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates)) { var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier); var KOObservationDatesArr = ko.Item2.Split(';'); if (KOObservationDatesArr.Length > 0) { model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate); model.ObserveEndDate = observeEndDate; if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value)) { model.ObserveType = "TERMINAL"; } } } else { oSd = model.StartDate.Value.AddDays(1); model.ObserveStartDate = oSd; model.ObserveEndDate = model.EndDate; } break; } } /// /// 是否是到期观察 /// /// /// /// public bool isTerminal(string observationDates, DateTime endDate) { var isTerminal = false; var observations = observationDates.Split(','); if (observations.Length == 1) { var observeStartData = DateTime.Parse(observations[0]); if (observeStartData == endDate) { isTerminal = true; } } return isTerminal; } /// /// 获取收益计算方式 /// /// private void formatRevenueCalculationMethod(SuperviseReportBaseModel model) { var trade = model.trade; switch (model.OptionProductStructure) { case "AS": break; case "DI": model.RevenueCalculationMethod = trade.trade_binary_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT"; break; case "RA": break; case "SF": case "SKI": model.RevenueCalculationMethod = trade.trade_barrier_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT"; break; case "DSF": if (model.ProductType == "双鲨期权") { model.RevenueCalculationMethod = trade.trade_double_sharkfin_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT"; } else { model.RevenueCalculationMethod = trade.trade_barrier_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT"; } break; case "AC": break; case "SA": case "GSA": model.RevenueCalculationMethod = trade.trade_snowball.KORebateType == 0 ? "HIT" : "EXPIRY"; break; case "PA": model.RevenueCalculationMethod = trade.trade_autocall.CouponPayType == 0 ? "HIT" : "EXPIRY"; break; } } /// /// 设置特定期权结构的字段 需要大改 /// /// private void setOptionlFields(SuperviseReportBaseModel model) { var trade = model.trade; switch (model.OptionProductStructure) { case "DI"://二元 if (trade.trade_binary_option != null) { model.ExerciseBenefitsSymbol = "1"; if (trade.IsUsePremiumRate == true) { model.ExerciseBenefitsSymbol = "2"; model.ExerciseBenefits = trade.trade_binary_option.CashOrNothingAmountRate + (model.GuaranteedIncome ?? 0); if (model.Strike2 > 0) { model.ExerciseBenefits2 = trade.trade_binary_option.CashOrNothingAmountHighRate + (model.GuaranteedIncome ?? 0); } } else { model.ExerciseBenefitsCurrency = "CNY"; model.ExerciseBenefits = trade.trade_binary_option.CashOrNothingAmount + (model.GuaranteedIncome ?? 0); if (model.Strike2 > 0) { model.ExerciseBenefits2 = trade.trade_binary_option.CashOrNothingAmountHigh + (model.GuaranteedIncome ?? 0); } } } break; case "RA": if (trade.trade_rangeaccrual != null) { model.ExerciseBenefitsSymbol = "2"; model.ExerciseBenefits = trade.trade_rangeaccrual.BonusRate + (trade.PrincipalRateWrite ?? 0); } break; case "SKI": case "SF": if (trade.trade_barrier_option != null) { model.BarriersPrice = trade.trade_barrier_option.BarrierPrice; if (!string.IsNullOrEmpty(trade.trade_barrier_option.BarrierType)) { if (trade.trade_barrier_option.BarrierType.StartsWith("上")) { model.BarriersPriceTouchDirection = "Up"; } else if (trade.trade_barrier_option.BarrierType.StartsWith("下")) { model.BarriersPriceTouchDirection = "Down"; } if (trade.trade_barrier_option.BarrierType.EndsWith("敲入")) { model.BarriersPriceType = "In"; } else if (trade.trade_barrier_option.BarrierType.EndsWith("敲出")) { model.BarriersPriceType = "Out"; } } if (model.trade.IsMoneynessOption == "是") { model.BarriersPrice = trade.trade_barrier_option.BarrierPrice * trade.SpotPrice; } model.CompensationIncomeCurrency = "CNY"; if (trade.IsUsePremiumRate == true) { model.CompensationIncomeSymbol = "2"; model.CompensationIncome = trade.trade_barrier_option.RebateRate ?? 0; model.CompensationIncomeCurrency = null; } else { model.CompensationIncomeSymbol = "1"; model.CompensationIncome = trade.trade_barrier_option.Rebate ?? 0; } } break; case "DSF": model.CompensationIncomeCurrency = "CNY"; if (model.ProductType == "双鲨期权") { if (trade.trade_double_sharkfin_option != null) { model.BarriersPrice = trade.trade_double_sharkfin_option.BarrierLow; model.BarriersPrice2 = trade.trade_double_sharkfin_option.BarrierHigh; if (model.trade.IsMoneynessOption == "是") { model.BarriersPrice = trade.trade_double_sharkfin_option.BarrierLow * trade.SpotPrice; model.BarriersPrice2 = trade.trade_double_sharkfin_option.BarrierHigh * trade.SpotPrice; } model.BarriersPriceTouchDirection = "Down"; model.BarriersPrice2TouchDirection = "Up"; model.BarriersPriceType = "Out"; model.BarriersPrice2Type = "Out"; if (trade.IsUsePremiumRate == true) { model.CompensationIncome = trade.trade_double_sharkfin_option.RebateRate ?? 0; model.CompensationIncome2 = trade.trade_double_sharkfin_option.RebateHighRate ?? 0; model.CompensationIncomeSymbol = "2"; model.CompensationIncomeCurrency = null; } else { model.CompensationIncome = trade.trade_double_sharkfin_option.Rebate ?? 0; model.CompensationIncome2 = trade.trade_double_sharkfin_option.RebateHigh ?? 0; model.CompensationIncomeSymbol = "1"; } } } else { if (trade.trade_barrier_option != null) { model.BarriersPrice = trade.trade_barrier_option.BarrierPrice; model.BarriersPrice2 = trade.trade_barrier_option.UpperBarrierPrice; if (model.trade.IsMoneynessOption == "是") { model.BarriersPrice = trade.trade_barrier_option.BarrierPrice * trade.SpotPrice; model.BarriersPrice2 = trade.trade_barrier_option.UpperBarrierPrice * trade.SpotPrice; } model.BarriersPriceTouchDirection = "Down"; if (!string.IsNullOrEmpty(trade.trade_barrier_option.BarrierType)) { if (trade.trade_barrier_option.BarrierType.EndsWith("敲入")) { model.BarriersPriceType = "In"; if (model.BarriersPrice2 > 0) { model.BarriersPrice2Type = "In"; model.BarriersPrice2TouchDirection = "Up"; } } else if (trade.trade_barrier_option.BarrierType.EndsWith("敲出")) { model.BarriersPriceType = "Out"; if (model.BarriersPrice2 > 0) { model.BarriersPrice2Type = "Out"; model.BarriersPrice2TouchDirection = "Up"; } } } if (trade.IsUsePremiumRate == true) { model.CompensationIncome = trade.trade_barrier_option.RebateRate ?? 0; model.CompensationIncome2 = trade.trade_barrier_option.RebateHighRate ?? 0; model.CompensationIncomeSymbol = "2"; model.CompensationIncomeCurrency = null; } else { model.CompensationIncome = trade.trade_barrier_option.Rebate ?? 0; model.CompensationIncome2 = trade.trade_barrier_option.RebateHigh ?? 0; model.CompensationIncomeSymbol = "1"; } } } break; case "SA": case "GSA": if (trade.trade_snowball != null) { double? saKOPrice, saKIPrice; saKOPrice = trade.trade_snowball.KOBarrier; //敲出障碍价 if (!string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates)) { var saKoResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates); if (saKoResult.Item2 != null) { var latestKOObservationDate = saKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault(); saKOPrice = saKoResult.Item2[GetDateIndex(saKoResult.Item1, latestKOObservationDate)]; } } //敲入障碍价 saKIPrice = trade.trade_snowball.KIBarrier; if (!string.IsNullOrEmpty(trade.trade_snowball.ObservationDates)) { var saKiResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates); if (saKiResult.Item2 != null) { var latestKIObservationDate = saKiResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault(); saKIPrice = saKiResult.Item2[GetDateIndex(saKiResult.Item1, latestKIObservationDate)]; } } if (trade.trade_snowball.KIPayoffType != 0) { model.KnockInBarrierPrice = saKIPrice; if (model.trade.IsMoneynessOption == "是") { model.KnockInBarrierPrice = saKIPrice * trade.SpotPrice; } } model.KnockOutBarrierPrice = saKOPrice; if (model.trade.IsMoneynessOption == "是") { model.KnockOutBarrierPrice = saKOPrice * trade.SpotPrice; } if (model.GuaranteedIncomeSymbol == "2") { model.CouponAnnualRate = trade.trade_snowball.KORebate + (model.GuaranteedIncome ?? 0); } else { model.CouponAnnualRate = trade.trade_snowball.KORebate + ((trade.OriginalPrincipalSum ?? 0) / trade.StockEqvNotional); } //雪球敲出时,判断敲出日期是否小杨到期日,是的话,提前终止日期需赋值 if (!string.IsNullOrEmpty(trade.trade_snowball.KnockInOutStatus) && (trade.trade_snowball.KnockInOutStatusCn.Contains("敲出") || trade.trade_snowball.KnockInOutStatus.ToLower().Contains("out"))) { if (trade.trade_snowball.KnockInOutDate < model.EndDate) { model.UnWindDate = trade.trade_snowball.KnockInOutDate; } } } break; case "PA": if (trade.trade_autocall != null) { double? paKOPrice, paKIPrice, paCoupon, couponRate; paKOPrice = trade.trade_autocall.KOBarrier; paCoupon = trade.trade_autocall.CouponBarrier; couponRate = trade.trade_autocall.Coupon; //敲出障碍价、Coupon障碍价 if (!string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates)) { var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier); var paKoResult = QdpHelper.ParseAutocallCustomizedInfoV3(ko.Item2); //敲出观察频率 if (paKoResult.Item2 != null) { var latestKOObservationDate = paKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault(); paKOPrice = paKoResult.Item2[GetDateIndex(paKoResult.Item1, latestKOObservationDate)]; } //票息观察频率 var CouponKoResult = QdpHelper.ParseAutocallCustomizedInfo(ko.Item1); if (CouponKoResult.Item3 != null) { var latestKOObservationDate = CouponKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault(); couponRate = CouponKoResult.Item3[GetDateIndex(CouponKoResult.Item1, latestKOObservationDate)]; } } //敲入障碍价 paKIPrice = trade.trade_autocall.KIBarrier; if (!string.IsNullOrEmpty(trade.trade_autocall.ObservationDates)) { var paKiResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates); if (paKiResult.Item2 != null) { var latestKIObservationDate = paKiResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault(); paKIPrice = paKiResult.Item2[GetDateIndex(paKiResult.Item1, latestKIObservationDate)]; } } model.KnockInBarrierPrice = paKIPrice; model.KnockOutBarrierPrice = paKOPrice; model.CouponBarrierPrice = paCoupon; if (model.trade.IsMoneynessOption == "是") { model.KnockInBarrierPrice = paKIPrice * trade.SpotPrice; model.KnockOutBarrierPrice = paKOPrice * trade.SpotPrice; model.CouponBarrierPrice = paCoupon * trade.SpotPrice; } if (model.GuaranteedIncomeSymbol == "2") { model.CouponAnnualRate = couponRate + (model.GuaranteedIncome ?? 0); } else { model.CouponAnnualRate = couponRate + (trade.OriginalPrincipalSum / trade.SpotPrice); } //凤凰敲出时,判断敲出日期是否小杨到期日,是的话,提前终止日期需赋值 if (!string.IsNullOrEmpty(trade.trade_autocall.KnockInOutStatus) && (trade.trade_autocall.KnockInOutStatusCn.Contains("敲出") || trade.trade_autocall.KnockInOutStatus.ToLower().Contains("out"))) { if (trade.trade_autocall.KnockInOutDate < model.EndDate) { model.UnWindDate = trade.trade_autocall.KnockInOutDate; } } } break; } } /// /// 设置远期结构的字段 /// /// private void setForwardFields(SuperviseReportBaseModel model) { var trade = model.trade; model.ForwardPrice = trade.Strike; model.ForwardPriceCurrency = "CNY"; model.ForwardPriceSymbol = "1"; //保底收益 if (model.GuaranteedIncome == null) { model.GuaranteedIncome = 0; model.GuaranteedIncomeSymbol = "1"; model.GuaranteedIncomeCurrency = "CNY"; } } /// /// 设置互换结构的字段 /// /// private void setSwapFields(SuperviseReportBaseModel model) { var trade = model.trade; var tSwap = trade.trade_swap; model.FixedIncomeCurrency = "CNY"; if (tSwap.IsGetFloatingProfit) { if (tSwap.GetLongShort == "多头") { model.FloatingDirection = "1"; } else { model.FloatingDirection = "2"; } } else { model.FixedIncome = tSwap.GetSwapRate; model.FixedIncomeSymbol = "2"; model.FixedIncomeCurrency = null; } if (tSwap.IsPayFloatingProfit) { if (tSwap.PayLongShort == "多头") { model.FloatingDirection = "1"; } else { model.FloatingDirection = "2"; } } else { model.FixedIncome = tSwap.PaySwapRate; model.FixedIncomeSymbol = "2"; model.FixedIncomeCurrency = null; } //互换交易,设置了互换利率的话,固定收益又没设置,就读取互换利率的最后一个 if (model.FixedIncome <= 0) { if (!string.IsNullOrEmpty(tSwap.GetSwapTimeAndRate)) { var swapTiamAndRateArr = tSwap.GetSwapTimeAndRate.Split(';'); if (swapTiamAndRateArr.Length >= 1) { var swapRateArr = swapTiamAndRateArr[1]?.Split(','); model.FixedIncome = double.Parse(swapRateArr[swapRateArr.Length - 1]); model.FixedIncomeSymbol = "2"; } } } } /// /// 自定义字段结构不为空时,处理自定义字段报送 /// /// private void formatExtendInfo(SuperviseReportBaseModel item) { var stInfo = DbContext.Structure_Info.FirstOrDefault(n => n.StructureName == item.StructureType); if (stInfo == null) { return; } item.OptionProductStructure = string.IsNullOrWhiteSpace(stInfo.StructureTypeSm) ? "O" : stInfo.StructureTypeSm; var stDetail = DbContext.Structure_Details.Where(n => n.StructureId == stInfo.id).ToList(); if (stDetail.Count == 0) { return; } formatCustomProductStructure(item, stInfo, stDetail); } /// /// 自定义结构初始化 /// /// /// /// private void formatCustomProductStructure(SuperviseReportBaseModel model, Structure_Info structure, List structureDetail) { var sdInfoList = JsonHelper.Deserialize>(model.ExtendInfo); string v1, v2, v3, v4, v5, v6, v7, v8, v9, v10; switch (structure.StructureTypeSm) { case "DI": case "RA": case "AC": v1 = GetCustomVal(structureDetail, sdInfoList, "行权收益1"); v2 = GetCustomVal(structureDetail, sdInfoList, "行权收益2"); v3 = GetCustomVal(structureDetail, sdInfoList, "行权收益3"); v4 = GetCustomVal(structureDetail, sdInfoList, "行权收益货币"); v5 = GetCustomVal(structureDetail, sdInfoList, "行权收益符号"); if (!string.IsNullOrEmpty(v1)) { model.ExerciseBenefits = NumericalProcessing(v1, out var isPercentage); } if (!string.IsNullOrEmpty(v2)) { model.ExerciseBenefits2 = NumericalProcessing(v2, out var isPercentage); } if (!string.IsNullOrEmpty(v3)) { model.ExerciseBenefits3 = NumericalProcessing(v3, out var isPercentage); } if (!string.IsNullOrEmpty(v4)) { model.ExerciseBenefitsCurrency = v4; } if (!string.IsNullOrEmpty(v5)) { model.ExerciseBenefitsSymbol = v5; } break; case "DSF": case "SKI": case "SF": v1 = GetCustomVal(structureDetail, sdInfoList, "障碍价1"); v2 = GetCustomVal(structureDetail, sdInfoList, "障碍价1触碰方向"); v3 = GetCustomVal(structureDetail, sdInfoList, "障碍价1类型"); v4 = GetCustomVal(structureDetail, sdInfoList, "障碍价2"); v5 = GetCustomVal(structureDetail, sdInfoList, "障碍价2触碰方向"); v6 = GetCustomVal(structureDetail, sdInfoList, "障碍价2类型"); v7 = GetCustomVal(structureDetail, sdInfoList, "补偿收益1"); v8 = GetCustomVal(structureDetail, sdInfoList, "补偿收益2"); v9 = GetCustomVal(structureDetail, sdInfoList, "补偿收益货币"); v10 = GetCustomVal(structureDetail, sdInfoList, "补偿收益符号"); if (!string.IsNullOrEmpty(v1)) { model.BarriersPrice = NumericalProcessing(v1, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.BarriersPrice = model.BarriersPrice * model.trade.OriginalStockEqvNotional; } } else { model.BarriersPrice = null; } if (!string.IsNullOrEmpty(v2)) { model.BarriersPriceTouchDirection = getCustomBarriersFiled(v2); } if (!string.IsNullOrEmpty(v3)) { model.BarriersPriceType = getCustomBarriersFiled(v3); } if (!string.IsNullOrEmpty(v4)) { model.BarriersPrice2 = NumericalProcessing(v4, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.BarriersPrice2 = model.BarriersPrice2 * model.trade.OriginalStockEqvNotional; } } else { model.BarriersPrice2 = null; } if (!string.IsNullOrEmpty(v5)) { model.BarriersPrice2TouchDirection = getCustomBarriersFiled(v5); } if (!string.IsNullOrEmpty(v6)) { model.BarriersPrice2Type = getCustomBarriersFiled(v6); } if (!string.IsNullOrEmpty(v7)) { model.CompensationIncome = NumericalProcessing(v7, out var isPercentage); } else { model.CompensationIncome = null; } if (!string.IsNullOrEmpty(v8)) { model.CompensationIncome2 = NumericalProcessing(v8, out var isPercentage); } else { model.CompensationIncome2 = null; } if (!string.IsNullOrEmpty(v9)) { model.CompensationIncomeCurrency = v9; } if (!string.IsNullOrEmpty(v10)) { model.CompensationIncomeSymbol = v10; } break; case "SA": case "GSA": case "PA": v1 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲入障碍价"); v2 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲入观察期"); v3 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲出障碍价"); v4 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-Coupon障碍价"); v5 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-Coupon年化收益率"); if (!string.IsNullOrEmpty(v1)) { model.KnockInBarrierPrice = NumericalProcessing(v1, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.KnockInBarrierPrice = model.KnockInBarrierPrice * model.trade.OriginalStockEqvNotional; } } else { model.KnockInBarrierPrice = null; } if (!string.IsNullOrEmpty(v2)) { model.KnockInObservationPeriod = v2; } if (!string.IsNullOrEmpty(v3)) { model.KnockOutBarrierPrice = NumericalProcessing(v3, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.KnockOutBarrierPrice = model.KnockOutBarrierPrice * model.trade.OriginalStockEqvNotional; } } else { model.KnockOutBarrierPrice = null; } if (!string.IsNullOrEmpty(v4)) { model.CouponBarrierPrice = NumericalProcessing(v4, out var isPercentage); } else { model.CouponBarrierPrice = null; } if (!string.IsNullOrEmpty(v5)) { model.CouponAnnualRate = NumericalProcessing(v5, out var isPercentage); } else { model.CouponAnnualRate = null; } break; } #region 黑箱自定义基础字段 string customObserveType, customObserveStartDate, customObserveEndDate, customObservationPeriod, customObservePeriodMultiplier, customRevenueCalculationMethod, customGuaranteedIncome, customGuaranteedIncomeCurrency, customGuaranteedIncomeSymbol, customStrike1, customStrike2, customStrike3, customStrikeCurrency, customStrikeSymbol, customExerciseMode, customOptionType, customExerciseDate, customValidDays; customExerciseMode = GetCustomVal(structureDetail, sdInfoList, "期权行权时间类型"); customOptionType = GetCustomVal(structureDetail, sdInfoList, "期权权利类型"); customExerciseDate = GetCustomVal(structureDetail, sdInfoList, "行权日"); customStrike1 = GetCustomVal(structureDetail, sdInfoList, "执行价格1"); customStrike2 = GetCustomVal(structureDetail, sdInfoList, "执行价格2"); customStrike3 = GetCustomVal(structureDetail, sdInfoList, "执行价格3"); customStrikeCurrency = GetCustomVal(structureDetail, sdInfoList, "执行价格货币"); customStrikeSymbol = GetCustomVal(structureDetail, sdInfoList, "执行价格符号"); customObserveType = GetCustomVal(structureDetail, sdInfoList, "观察类型"); customObserveStartDate = GetCustomVal(structureDetail, sdInfoList, "观察起始日"); customObserveEndDate = GetCustomVal(structureDetail, sdInfoList, "观察结束日"); customObservationPeriod = GetCustomVal(structureDetail, sdInfoList, "观察周期"); customObservePeriodMultiplier = GetCustomVal(structureDetail, sdInfoList, "观察周期乘数"); customRevenueCalculationMethod = GetCustomVal(structureDetail, sdInfoList, "收益计算方式"); customGuaranteedIncome = GetCustomVal(structureDetail, sdInfoList, "保底收益"); customGuaranteedIncomeCurrency = GetCustomVal(structureDetail, sdInfoList, "保底收益货币"); customGuaranteedIncomeSymbol = GetCustomVal(structureDetail, sdInfoList, "保底收益符号"); customValidDays = GetCustomVal(structureDetail, sdInfoList, "一年有效天数"); if (!string.IsNullOrEmpty(customValidDays)) { model.ValidDaysStr = customValidDays; } if (!string.IsNullOrEmpty(customExerciseMode)) { model.ExerciseMode = getCustomExerciseMode(customExerciseMode); } else { model.ExerciseMode = null; } if (!string.IsNullOrEmpty(customOptionType)) { model.OptionType = getCustomOptionType(customOptionType); } else { model.OptionType = null; } if (!string.IsNullOrEmpty(customExerciseDate)) { model.ExerciseDate = DateTime.Parse(customExerciseDate); } else { model.ExerciseDate = null; } if (!string.IsNullOrEmpty(customStrike1)) { model.Strike = NumericalProcessing(customStrike1, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.Strike = ((model.Strike * model.trade.SpotPrice) ?? 0); } } else { model.Strike = null; } if (!string.IsNullOrEmpty(customStrike2)) { model.Strike2 = NumericalProcessing(customStrike2, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.Strike2 = ((model.Strike2 * model.trade.SpotPrice) ?? 0); } } else { model.Strike2 = null; } if (!string.IsNullOrEmpty(customStrike3)) { model.Strike3 = NumericalProcessing(customStrike3, out var isPercentage); if (model.trade.IsMoneynessOption == "是" && isPercentage) { model.Strike3 = ((model.Strike3 * model.trade.SpotPrice) ?? 0); } } else { model.Strike3 = null; } if (!string.IsNullOrEmpty(customStrikeCurrency)) { model.StrikeCurrency = customStrikeCurrency; } else if (model.Strike != null) { if (model.UnderlyingInitialPriceSymbol == "1") { model.StrikeCurrency = "CNY"; } } else { model.StrikeCurrency = null; } if (!string.IsNullOrEmpty(customStrikeSymbol)) { model.StrikeSymbol = customStrikeSymbol; } else if (model.Strike != null) { model.StrikeSymbol = model.UnderlyingInitialPriceSymbol; } else { model.StrikeSymbol = null; } if (!string.IsNullOrEmpty(customObserveType)) { model.ObserveType = getCustomObType(customObserveType).ToUpper(); } if (!string.IsNullOrEmpty(customObserveStartDate)) { model.ObserveStartDate = DateTime.Parse(customObserveStartDate); } if (!string.IsNullOrEmpty(customObserveEndDate)) { model.ObserveEndDate = DateTime.Parse(customObserveEndDate); } if (!string.IsNullOrEmpty(customObservationPeriod)) { model.ObservationPeriod = getCustomOBPeriod(customObservationPeriod).ToUpper(); } if (!string.IsNullOrEmpty(customObservePeriodMultiplier)) { model.ObservePeriodMultiplier = NumericalProcessing(customObservePeriodMultiplier, out var isPercentage); } else { model.ObservePeriodMultiplier = null; } if (!string.IsNullOrEmpty(customRevenueCalculationMethod)) { model.RevenueCalculationMethod = getCustomRCMethod(customRevenueCalculationMethod).ToUpper(); } if (!string.IsNullOrEmpty(customGuaranteedIncome)) { model.GuaranteedIncome = NumericalProcessing(customGuaranteedIncome, out _); } else { model.GuaranteedIncome = null; } if (!string.IsNullOrEmpty(customGuaranteedIncomeSymbol)) { model.GuaranteedIncomeSymbol = customGuaranteedIncomeSymbol; } else if (model.GuaranteedIncome != null) { model.GuaranteedIncomeSymbol = "1"; } else { model.GuaranteedIncomeSymbol = null; } if (!string.IsNullOrEmpty(customGuaranteedIncomeCurrency)) { model.GuaranteedIncomeCurrency = customGuaranteedIncomeCurrency; } else if (!string.IsNullOrWhiteSpace(model.GuaranteedIncomeSymbol) && model.GuaranteedIncomeSymbol == "1") { model.GuaranteedIncomeCurrency = "CNY"; } else { model.GuaranteedIncomeCurrency = null; } #endregion } /// /// 关联获取数据 /// /// /// /// /// private string GetCustomVal(List structureDetail, List sdInfoList, string FieldNameSm) { var query = (from sd in sdInfoList join std in structureDetail on sd.name.ToLower() equals std.ColumnName.ToLower() where (!string.IsNullOrWhiteSpace(std.FieldNameSm) && std.FieldNameSm == FieldNameSm) || (string.IsNullOrWhiteSpace(std.FieldNameSm) && std.ColumnName == FieldNameSm) select sd).FirstOrDefault(); return query == null ? "" : query.value; } /// /// 数值处理 /// /// /// private double NumericalProcessing(string inpVal, out bool isPercentage) { double resultVal = 0; isPercentage = false; if (inpVal.IndexOf(',') >= 0) { inpVal = inpVal.Replace(",", ""); } if (inpVal.EndsWith("%")) { isPercentage = true; inpVal = inpVal.Replace("%", ""); } resultVal = Convert.ToDouble(inpVal); if (isPercentage) { resultVal = resultVal / 100; } return resultVal; } private string getCustomObType(string input) { switch (input) { case "离散": case "离散观察": return "DISCRETE"; case "连续": case "连续观察": return "CONTINUOUS"; case "到期": case "到期观察": return "TERMINAL"; default: return input; } } private string getCustomOBPeriod(string inputVal) { switch (inputVal) { case "日度": case "D": case "d": return "DAIL"; case "周度": case "W": case "w": return "WEEK"; case "月度": case "M": case "m": return "MNTH"; case "年度": case "Y": case "y": return "YEAR"; default: return inputVal; } } private string getCustomRCMethod(string input) { switch (input) { case "递延至期末支付": return "EXPIRY"; case "即期计算": case "立即支付": return "HIT"; default: return input; } } private string getCustomBarriersFiled(string input) { switch (input) { case "向上": return "Up"; case "向下": return "Down"; case "敲入": return "In"; case "敲出": return "Out"; default: return input; } } /// /// 黑箱自定义期权行权时间类型 /// /// /// private string getCustomExerciseMode(string input) { switch (input) { case "欧式": return "EU"; case "美式": return "US"; case "百慕大": return "BD"; case "其他": return "O"; default: return input; } } /// /// 黑箱自定义期权权利类型 /// /// /// private string getCustomOptionType(string input) { switch (input.ToLower()) { case "put": case "看跌": return "1"; case "call": case "看涨": return "2"; case "chooser": return "3"; case "其他": case "价差": return "9"; default: return input; } } private int GetDateIndex(Date[] source, Date value) { var index = 0; foreach (var item in source) { if (item.DateTime == value.DateTime) { return index; } index++; } return -1; } } }