从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 凤凰期权敲出计算服务
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user