using Qdp.Pricing.Library.Options.Products.Autocall.Phoenix; using YLErp.Abstract; using YLErp.BLL; using YLErp.Modules.CalculationModule; using YLErp.Modules.TradeModule.KnockOutModule.Dto; namespace YLErp.Modules.TradeModule.KnockOutModule { /// /// 凤凰期权敲出计算服务 /// public class AutocallTradeKnockOutService : ITradeKnockOutService { public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate, ITradeExtendDataProvider _tradeExtendDataProvider) { var autocallOption = _tradeExtendDataProvider.GetTrade_Autocall_Option(td.id); if (autocallOption == null) { return new GetKnockOutPayoffResult { IsKnockOut = false }; } td.trade_autocall = autocallOption; return GetKnockOutPayoff(td, underlyingPrice, _valueDate); } public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate) { var result = new GetKnockOutPayoffResult { IsKnockOut = false }; var autocallOption = td.trade_autocall; if (autocallOption == null) { return result; } //1、获取敲出观察日期 var optionTrade = QdpTradeBuilder.GetAutocallOptionTrade(td, autocallOption, new OptionTradeParamRequest(valuedateBLL.SysRiskFreeRate()) { ParamOverride = x => { x.notional = td.Notional; } }); var autocall = (AutoCall)optionTrade.Instrument; var kiBarrier = td.IsMoneynessOptionData ? autocallOption.KIBarrier * td.SpotPrice : autocallOption.KIBarrier; var isCall = ConsGlobal.CallPut.IsCall(td.CallPut); if (autocall.KOObsDates.Select(x => x.DateTime).Contains(_valueDate)) //当前日为观察日 { //2、敲出判断 double koBarrier; if (autocall.CustomizedKOBarriers != null && autocall.CustomizedKOBarriers.Length > 0) { var index = autocall.KOObsDates.Select(x => x.DateTime).ToList().IndexOf(_valueDate); koBarrier = autocall.CustomizedKOBarriers[index]; } else { koBarrier = autocallOption.KOBarrier; } if (td.IsMoneynessOptionData) { koBarrier *= td.SpotPrice ?? 1.0; } //看涨 - 向上敲出,看跌 - 向下敲出 var isKnockedOut = isCall ? underlyingPrice >= koBarrier : underlyingPrice <= koBarrier; if (isKnockedOut) { result.IsKnockOut = true; var couponBarrier = td.IsMoneynessOptionData ? autocallOption.CouponBarrier * td.SpotPrice : autocallOption.CouponBarrier; if (isCall ? underlyingPrice >= couponBarrier : underlyingPrice <= couponBarrier) // 与派息障碍价格比较 { var observation = autocall.GetEffectiveObservation(_valueDate, includeTradeStartDate: autocallOption.CouponIncludeStartDate == true && autocallOption.CouponDayCount != "Monthly"); if (observation != null) { result.Payoff = observation.PaymentAmount; } } if (autocallOption.CouponPayType == CouponPayTypeEnum.AtCreated) //如果是产生时支付,持仓payoff为当日票息 { return result; } //如果到期支付 或者 敲出支付 持仓payoff加上之前的票息 using (var db = DbContextFactory.GetYLDbContext()) { var obsAmount = db.autocall_observation.Where(o => o.TradeId == td.id && o.EndDate != _valueDate).Sum(p => p.PaymentAmount); result.Payoff += obsAmount; } return result; } } return result; } } }