using NPOI.SS.Formula.Functions; using Qdp.Foundation.Implementations; using Qdp.Pricing.Library.Options.Products.Autocall.Snowball; using YLErp.Modules.CalculationModule; using YLErp.Modules.TradeModule.ExoticOptionModule; namespace YLErp.Modules.TradeModule { public class TradeSnowballService : YLBaseService { public TradeSnowballService(OptUserInfo userInfo) : base(userInfo) { } public TradeSnowballService(YLBaseService baseService) : base(baseService) { } public List GetObservations(int tradeId, DateTime valueDate) { var trade = DbContext.trade.FirstOrDefault(t => t.id == tradeId); var tradeSnowball = DbContext.trade_snowball.FirstOrDefault(t => t.TradeId == tradeId); if (trade == null || tradeSnowball == null) { return null; } // 如果是敲出转期权,则不支付票息 if (tradeSnowball.KOPayoffType != KOPayoffTypeEnum.Rebate) { return null; } if (trade.TradeStatus == ConsTrade.已到期 || trade.TradeStatus == ConsTrade.已执行 || trade.TradeStatus.Contains("待确认")) { return null; } var optionTrade = QdpTradeBuilder.GetSnowballOptionTrade(trade, tradeSnowball); if (optionTrade == null) { return null; } var snowball = (SimpleSnowball)optionTrade.Instrument; var observationEndDate = tradeSnowball.KnockInOutStatus == ConsTrade.KnockState.KnockedOut ? tradeSnowball.KnockInOutDate.Value : valueDate; var qdpEndDate = new Date(observationEndDate); qdpEndDate = snowball.KOObsDates.Where(d => d <= qdpEndDate).Max(); var observation = snowball.GetEffectiveObservation(qdpEndDate, tradeSnowball.CouponIncludeStartDate ?? false); if (tradeSnowball.PrepaymentUsed) { var payoff = new SpecialSnowballObservationHelper(trade, tradeSnowball).GetEffectiveObservation(qdpEndDate, optionTrade.Notional); observation = payoff == null ? null : new Qdp.Pricing.Library.Options.Products.Autocall.Phoenix.ObservationPayment { CouponRate = payoff.CouponRate, EndDate = payoff.CouponEndDate, PaymentAmount = payoff.CouponPaymentAmount, PaymentDate = qdpEndDate, StartDate = payoff.CouponStartDate, Notional = Math.Abs(optionTrade.Notional * (trade.SpotPrice ?? 0)) }; } if (observation == null) { return null; } else { var tradeCashCoupon = DbContext.trade_cash.FirstOrDefault(t => t.TradeId == tradeId && t.Action == "系统操作-票息" && t.ValidState != "InValid" && !t.IsDeleted); var tradeCashDetial = tradeCashCoupon != null ? DbContext.trade_cash_detail.FirstOrDefault(x => x.TradeCashId == tradeCashCoupon.id && x.Action == "系统操作-期权费") : null; return new List() { new autocall_observation { StartDate = observation.StartDate.DateTime, EndDate = observation.EndDate.DateTime, CouponRate = observation.CouponRate, StockEqvNotional = Math.Abs(observation.Notional), PaymentAmount = observation.PaymentAmount, AnnualizedPremiumRate = tradeSnowball.AnnualizedPremiumRate, AnnualizedTradePrice = tradeCashDetial?.Amount ?? 0, PaymentDate = tradeSnowball.KnockInOutStatus == ConsTrade.KnockState.KnockedOut ? tradeCashCoupon?.ValueDate ?? observationEndDate: observation.PaymentDate.DateTime } }; } } public double GetKOOptionPayoff(int tradeId, DateTime valueDate, double price) { var trade = DbContext.trade.AsNoTracking().FirstOrDefault(t => t.id == tradeId); var tradeSnowball = DbContext.trade_snowball.AsNoTracking().FirstOrDefault(t => t.TradeId == tradeId); return GetKOOptionPayoff(trade, tradeSnowball, valueDate, price); } public double GetKOOptionPayoff(OtcTradeBase trade, trade_snowball tradeSnowball, DateTime valueDate, double price) { if (trade == null || tradeSnowball == null) { return 0.0; } if (tradeSnowball.KOPayoffType == KOPayoffTypeEnum.Rebate) { return 0.0; } var optionTrade = QdpTradeBuilder.GetSnowballOptionTrade(trade, tradeSnowball); var snowball = (SimpleSnowball)optionTrade.Instrument; var payoffs = snowball.GetKOPayoff(new Date(valueDate), price); if (payoffs != null && payoffs.Length > 0) { return payoffs[0].PaymentAmount; } else { return 0.0; } } } }