using CxxCalcLib; using Qdp.Foundation.Implementations; using Qdp.Pricing.Base.Enums; using Qdp.Pricing.Base.Utilities; using YLErp.BLL.Calculation.V2; using YLErp.Commons; using YLErp.Enums; using YLErp.Modules.CalculationLogModule; using YLErp.QdpModule; namespace YLErp.Modules.CalculationModule { internal class SnowballSpecialistOptionCalculator { /// /// 计算Greeks /// /// /// /// /// public TradeValueResult CalcOptionValue(DateTime valueDate, double spotPrice, double vol, CalcScenarioEnum calcScenario, trade td) { return new TradeValueResult { Succeeded = false, ErrorMessage = "不支持专业版雪球" }; //using var wrapper = new CxxCalcApi(); //if (valueDate > td.ExerciseDate) //{ // //OTC-5920:对于定价日期>到期日的交易,无需给定价引擎计算,PV和其他希腊字母等直接为0即可。 // return new TradeValueResult(true) // { // UnderlyingCode = td.UnderlyingCode, // Pv = 0, // Delta = 0, // Gamma = 0, // Vega = 0, // Rho = 0, // CalendarDayTheta = 0, // TradingDayTheta = 0, // DeltaCash = 0, // GammaCash = 0, // VegaCash = 0, // Vol = vol, // SpotPrice = spotPrice // }; //} //var calcIn = BuildCalcInParams(valueDate, spotPrice, vol, td); //AddCalculationLog(calcIn, calcScenario); //Dictionary result1; //try //{ // result1 = wrapper.CalcPlatform_SnowballScenario(calcIn); //} //catch //{ // throw new ServiceException("存在不符合定价条件的交易,无法完成定价,请检查交易要素是否完备"); //} //var result = result1.Values.FirstOrDefault(); //var direction = td.BuySell == "买入" ? 1 : -1; //var valueResult = new TradeValueResult(true) //{ // UnderlyingCode = td.UnderlyingCode, // Pv = result.PV * direction, // Delta = result.DELTA * direction, // Gamma = result.GAMMA * direction, // Vega = result.VEGA * direction, // Rho = result.RHO * direction, // CalendarDayTheta = result.THETA * direction, // TradingDayTheta = result.THETA * direction, // DeltaCash = result.DELTA * spotPrice * direction, // GammaCash = result.GAMMA * spotPrice * spotPrice * 0.01 * direction, // VegaCash = result.VEGA * spotPrice * direction, // Vol = vol, // SpotPrice = spotPrice //}; //// 计算 RoundedPv //valueResult.RoundedPv = OtcFormatHelper.FormatValue(valueResult.Pv / td.Notional, 2) * td.Notional; ////计算DeltaInLots //var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(td.UnderlyingCode); //valueResult.DeltaInLots = TradeLotsCalc.CalcDeltaInLots(result.DELTA, null, underlying); ////if (!(td.trade_snowball?.PrepaymentAddedToPv ?? false)) ////{ //// // 计算引擎返回的PV是包含预付金,如果pv不想包含预付金,需要减掉预付金 //// var advanceAmount = td.StockEqvNotional * (td.trade_snowball.PrepaymentRatio ?? 0); //// valueResult.Pv -= advanceAmount; ////} //ValueCalculator.ConvertTradeValueResultOfCompany(valueResult, td.TradeType); //return valueResult; } /// /// 根据目标PV反算票息、波动率等 /// /// 定价日 /// 波动率 /// 计算的目标 /// 交易信息 /// public double CalcTargets(DateTime valueDate, double spotPrice, double vol, int calcTarget, trade td) { return 0; //using var wrapper = new CxxCalcApi(); //var calcIn = BuildCalcInParams(valueDate, spotPrice, vol, td); //var targetPv = td.TradePrice ?? 0.0; //var clacTarget = (CalcTarget)calcTarget; //var isNan = false; //if (clacTarget == CalcTarget.COUPON) //{ // //calcIn.koCoupons = calcIn.koCoupons.Select(g => double.NaN).ToArray(); // calcIn.maturityCoupon = double.NaN; // isNan = false; //} //else if (clacTarget == CalcTarget.KO_COUPON) //{ // //calcIn.koCoupons = calcIn.koCoupons.Select(g => double.NaN).ToArray(); // isNan = true; //} //else if (clacTarget == CalcTarget.MATURITY_COUPON) //{ // calcIn.maturityCoupon = double.NaN; // isNan = true; //} //AddCalculationLog(calcIn, CalcScenarioEnum.Pricing, targetPv, isNan); //double targetValue = 0; //try //{ // targetValue = wrapper.CalcPlatform_Infer(calcIn, targetPv, isNan, CalcTarget.COUPON); //} //catch //{ // throw new ServiceException("存在不符合定价条件的交易,无法完成反算,请检查交易要素是否完备"); //} //return targetValue; } /// /// 根据原始专业版雪球拆分为两个雪球 /// 此处获取拆分的专业版雪球 /// /// /// public trade GetSpecialTrade(trade td) { //预付金比例设置为0 var tdClone = td.Clone(); tdClone.trade_snowball = td.trade_snowball.Clone(); tdClone.trade_snowball.PrepaymentRatio = 0; return tdClone; } /// /// 根据原始专业版雪球拆分为两个雪球 /// 此处获取拆分的保本雪球 /// /// /// public trade GetBreakevenTrade(trade td) { //无敲入条款,敲出票息与红利票息(不年化)=原始雪球的预付金比例 //无风险利率=原始雪球的预付金折现率 var tdClone = td.Clone(); tdClone.trade_snowball = td.trade_snowball.Clone(); tdClone.trade_snowball.KnockInOutDate = null; tdClone.trade_snowball.KnockInOutStatus = null; tdClone.trade_snowball.KIBarrier = 0; tdClone.trade_snowball.SpreadStrikeAtMaturity1 = 0; tdClone.trade_snowball.KIPayoffType = KIPayoffTypeEnum.None; tdClone.trade_snowball.KORebate = td.trade_snowball.PrepaymentRatio ?? 0; tdClone.trade_snowball.Coupon = td.trade_snowball.PrepaymentRatio ?? 0; tdClone.trade_snowball.IsFixedCoupon = true; tdClone.trade_snowball.PrepaymentUsed = false; var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(td.trade_snowball.KOObservationDates); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; tdClone.trade_snowball.KOObservationDates = $"{string.Join(",", koObservationDates.Select(O => O.DateTime.OtcFormatDate()))};" + $"{string.Join(",", customizedKOBarriers)};" + $"{string.Join(",", koObservationDates.Select(x => (td.trade_snowball.PrepaymentRatio ?? 0).OtcFormatFlex(6)))}"; tdClone.NoRiskRate = td.trade_snowball.PrepaymentConvertCashRate ?? 0; return tdClone; } /// /// 加和result结果 /// /// /// /// public TradeValueResult MergeTradeValueResult(TradeValueResult specialSnowballResult, TradeValueResult breakevenSnowballResult) { specialSnowballResult.Pv += breakevenSnowballResult.Pv; specialSnowballResult.RoundedPv += breakevenSnowballResult.RoundedPv; specialSnowballResult.Delta += breakevenSnowballResult.Delta; specialSnowballResult.DeltaCash += breakevenSnowballResult.DeltaCash; specialSnowballResult.Gamma += breakevenSnowballResult.Gamma; specialSnowballResult.GammaCash += breakevenSnowballResult.GammaCash; specialSnowballResult.CalendarDayTheta += breakevenSnowballResult.CalendarDayTheta; specialSnowballResult.TradingDayTheta += breakevenSnowballResult.TradingDayTheta; specialSnowballResult.Rho += breakevenSnowballResult.Rho; specialSnowballResult.Vega += breakevenSnowballResult.Vega; specialSnowballResult.VegaCash += breakevenSnowballResult.VegaCash; specialSnowballResult.TimeValue += breakevenSnowballResult.TimeValue; return specialSnowballResult; } /// /// 构建计算引擎需要的参数 /// /// 定价日 /// 波动率 /// 交易信息 /// private CalcIn BuildCalcInParams(DateTime valueDate, double spotPrice, double vol, trade td) { var trade_snowball = td.trade_snowball; // 敲入观察日 if (string.IsNullOrEmpty(trade_snowball?.KOObservationDates?.Trim(new[] { ' ', ';' }))) { throw new ServiceException("敲出观察日列表不能为空,请生成敲出观察日列表"); } if (vol <= 0) { throw new ServiceException("波动率必须大于0,请调整波动率"); } var koParams = trade_snowball.KOObservationDates.Split(";"); var koObsDateStr = koParams[0]; var koObsDates = koObsDateStr.Split(",").Select(g => new Date(DateTime.Parse(g))).ToArray(); var koBarriers = koParams[1].Split(",").Select(g => double.Parse(g)).ToArray(); var koCoupons = koParams[2].Split(",").Select(g => string.IsNullOrEmpty(g) ? double.NaN : double.Parse(g)).ToArray(); var kiBarrier = trade_snowball.KIBarrier; var strike = trade_snowball.SpreadStrikeAtMaturity1 ?? 0; if (!td.IsMoneynessOptionData) { //转为相对价格比例 koBarriers = koBarriers.Select(g => g / td.InitialSpotPrice ?? 0).ToArray(); kiBarrier = kiBarrier / td.InitialSpotPrice ?? 0; strike = strike / td.InitialSpotPrice ?? 0; } // 计算票息年化系数(外部有不同的计算方式) var iFixedCoupon = string.IsNullOrEmpty(trade_snowball.CouponDayCount); //是否年化,约定为空表示非年化 var dayCount = iFixedCoupon ? null : trade_snowball.CouponDayCount.ToDayCountImpl(); var koFractions = koObsDateStr.Split(",").Select(g => { var koObsDate = DateTime.Parse(g); var koFraction = iFixedCoupon ? 1 : YLErp.QdpModule.QdpHelper.AnnualizeFactor(new Date(td.StartDate), koObsDate, dayCount); return koFraction; }).ToArray(); var market = GetMarket(td.UnderlyingCode); // 计算入参 var calcIn = new CalcIn() { // 市场(日历)名称,如China market = market, // 开始日期 startDate = new Date(td.StartDate).ToString(), // 估值日期 valueDate = valueDate.ToString("yyyy-MM-dd"), // 5是向上敲出的雪球,6是向下敲出的雪球 barrierType = QdpConverter.ConvertOptionType(td.CallPut) == OptionType.Call ? CxxCalcLib.BarrierType.UP_OUT_DOWN_IN : CxxCalcLib.BarrierType.UP_IN_DOWN_OUT, // 期初价格 initialSpot = td.InitialSpotPrice ?? 0, // 敲出观察日列表,以逗号分隔 koObsDateStr = koObsDateStr, // 敲出障碍价格列表,与敲出观察日对应 koBarriers = koBarriers, // 敲出票息列表?? koCoupons = koCoupons, // 敲出票息的年化系数列表 koFractions = koFractions, // 敲出观察日个数 activeKoObsCount = koObsDates.Count(),//koObsDates.Where(g => g > new Date(td.StartDate)).Count(), // 敲出增强收益的参与率,无增强收益填0 koPayoffParticipation = trade_snowball.EnhancedParticipationRate ?? 0, // 敲入障碍价格 kiBarrier = kiBarrier, // 敲入后的行权价 kiStrike = strike, // 是否仅在到期日进行敲入观察,否则为每日观察 kiObsOnlyAtMaturity = trade_snowball.KIObservationType == KIObservationType.OnlyEndDate, // 敲入后的期权参与率?? kiParticipationRate = trade_snowball.KIParticipationRate ?? 0, // 红利票息 maturityCoupon = trade_snowball.Coupon, // 保本比例,如0.8表示敲入后亏损封顶20% protectionRatio = trade_snowball.PrincipalProtectionRate ?? 0, // 初始预付金比例 initialMarginRatio = trade_snowball.PrepaymentRatio ?? 0, // 预付金利率 marginInterestRate = trade_snowball.PrepaymentInterestRate ?? 0, // 数量?? amount = td.Notional, // 是否已敲入 isKnockedIn = trade_snowball.IsInitialKnockedIn, // 一组标的资产价格,每个价格都是一个情景 spots = new double[] { spotPrice }, // 情景个数?? scenarioCount = 1, // 无风险利率 r = td.NoRiskRate ?? 0, // 分红率 q = td.DividendRate ?? 0, // 波动率 v = vol, // 计算指标,逗号隔开 greekType = "PV,DELTA,GAMMA,VEGA,THETA,RHO" }; return calcIn; } /// /// 添加日志 /// /// /// /// private static void AddCalculationLog(CalcIn CalcParams, CalcScenarioEnum calcScenario, double? targetPv = null, bool? isNan = null) { try { // 添加计算日志 var log = new CalculationLog() { CreateTime = DateTime.Now, Scenario = calcScenario, LogObject = CalcParams, //TradeNumber = tradeNumber, //Notional = CalcParams.amount, //Exercise = CalcParams..ToString(), //OptionType = CalcParams?.OptionType.ToString(), //TradeDate = trade.TradeDate?.ToString(), //MaturityDate = trade.MaturityDate?.ToString(), //InitialSpotPrice = option?.InitialSpotPrice.ToString(), //Strike = option?.Strike.ToString(), targetPv = targetPv, isNan = isNan }; ICalculationLogService calcLogService = new CalculationLogService(); calcLogService.AddLog(log, calcScenario); } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// /// 获取交易日历名称 /// /// /// private static string GetMarket(string underlyingCode) { var underlyingManager = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(underlyingCode); var market = DataCacheModule.DataCacheManager.GetMarketDataSource().AsQueryable(g => g.MarketName == underlyingManager.MarketName)?.FirstOrDefault(); return market?.CalendarName ?? "chn"; } } }