从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
using CsvHelper;
|
||||
using Qdp.Foundation.Implementations;
|
||||
using Qdp.Pricing.Library.Options.Products.Autocall.Snowball;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YLErp.Abstract;
|
||||
using YLErp.BLL;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.DBModels.Helpers;
|
||||
using YLErp.Modules.CalculationModule;
|
||||
using YLErp.Modules.TradeModule.ExoticOptionModule;
|
||||
using YLErp.Modules.TradeModule.KnockOutModule.Dto;
|
||||
|
||||
namespace YLErp.Modules.TradeModule.KnockOutModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 雪球期权敲出计算服务
|
||||
/// </summary>
|
||||
public class SnowBallTradeKnockOutService : ITradeKnockOutService
|
||||
{
|
||||
public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate, ITradeExtendDataProvider _tradeExtendDataProvider)
|
||||
{
|
||||
var snowBallOption = _tradeExtendDataProvider.GetTrade_Snowball_Option(td.id);
|
||||
if (snowBallOption == null)
|
||||
{
|
||||
return new GetKnockOutPayoffResult { IsKnockOut = false };
|
||||
}
|
||||
td.trade_snowball = snowBallOption;
|
||||
return GetKnockOutPayoff(td, underlyingPrice, _valueDate);
|
||||
}
|
||||
|
||||
public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate)
|
||||
{
|
||||
GetKnockOutPayoffResult result = new GetKnockOutPayoffResult { IsKnockOut = false };
|
||||
var snowBallOption = td.trade_snowball;
|
||||
if (snowBallOption == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (snowBallOption.PrepaymentUsed)
|
||||
{
|
||||
var specialSnowBallResult = new SpecialSnowballObservationHelper(td, snowBallOption).GetObservationResultForTraderSide(_valueDate, underlyingPrice, td.Notional);
|
||||
if (specialSnowBallResult != null && specialSnowBallResult.ResultType == SnowballObservationResultType.KoPayoff)
|
||||
{
|
||||
result.IsKnockOut = true;
|
||||
result.Payoff = specialSnowBallResult.PaymentAmount;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
var request = new OptionTradeParamRequest(valuedateBLL.SysRiskFreeRate())
|
||||
{
|
||||
ParamOverride = p => p.notional = td.Notional
|
||||
};
|
||||
|
||||
var optionTrade = QdpTradeBuilder.GetSnowballOptionTrade(td, snowBallOption, request);
|
||||
var snowball = (SimpleSnowball)optionTrade.Instrument;
|
||||
var isCall = ConsGlobal.CallPut.IsCall(td.CallPut);
|
||||
|
||||
if (snowball.KOObsDates.Select(x => x.DateTime).Contains(_valueDate))
|
||||
{
|
||||
(var koSettleDate, var koBarrier) = GetSnowBallKoSettleInfo(_valueDate, td, snowBallOption, snowball);
|
||||
// 发生敲出事件(看涨 - 向上敲出支付票息,看跌 - 向下敲出支付票息)
|
||||
if (isCall ? underlyingPrice >= koBarrier : underlyingPrice <= koBarrier)
|
||||
{
|
||||
result.IsKnockOut = true;
|
||||
if (snowball.UseOptionPayoffAtKO)
|
||||
{
|
||||
double paymentAmount = 0;
|
||||
var koOptionCashflows = snowball.GetKOPayoff(new Date(_valueDate), underlyingPrice);
|
||||
paymentAmount = TradeHelper.GetAmountByPaymentAmount(koOptionCashflows[0].PaymentAmount, td.PrincipalSum(), td.BuySell);
|
||||
result.Payoff = paymentAmount;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var CouponPayment = snowball.CouponPayment(_valueDate, includeStartDate: snowBallOption.CouponIncludeStartDate == true && snowBallOption.CouponDayCount != "Monthly");
|
||||
var couponPayment = TradeHelper.GetAmountByPaymentAmount(CouponPayment, td.PrincipalSum(), td.BuySell);
|
||||
if (snowBallOption.AnnualizedPremiumRate.HasValue && snowBallOption.AnnualizedPremiumRate != 0)
|
||||
{
|
||||
var tradePrice = (td.StockEqvNotional * td.ParticipationRate * snowBallOption.AnnualizedPremiumRate * snowball.CouponDayCount.CalcDayCountFraction(snowball.StartDate, new Date(_valueDate))) ?? 0;
|
||||
if (tradePrice != 0)
|
||||
{
|
||||
couponPayment += (td.BuySell == "买入" ? -1 : 1) * tradePrice;
|
||||
}
|
||||
}
|
||||
result.Payoff = couponPayment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//获取雪球期权敲出时要准备的信息
|
||||
public (DateTime koSettleDate, double koBarrier) GetSnowBallKoSettleInfo(DateTime valueDate, OtcTradeBase otcTrade, trade_snowball tradeSnowball, SimpleSnowball snowball)
|
||||
{
|
||||
double koBarrier;
|
||||
var koSettleDate = valueDate;
|
||||
var datesStr = tradeSnowball.KOObservationSettleDates;
|
||||
var KOObsSettleDates = string.IsNullOrWhiteSpace(datesStr) ? null : datesStr.Split(new char[] { ',', ';', ',', ';' }, StringSplitOptions.RemoveEmptyEntries).Select(x => DateTime.Parse(x)).ToArray();
|
||||
if (snowball.CustomizedKOBarriers != null && snowball.CustomizedKOBarriers.Length > 0)
|
||||
{
|
||||
var index = snowball.KOObsDates.Select(x => x.DateTime).ToList().IndexOf(valueDate);
|
||||
koBarrier = snowball.CustomizedKOBarriers[index];
|
||||
if (KOObsSettleDates != null && KOObsSettleDates.Length > index)
|
||||
{
|
||||
koSettleDate = KOObsSettleDates[index];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
koBarrier = tradeSnowball.KOBarrier;
|
||||
if (KOObsSettleDates != null && KOObsSettleDates.Any())
|
||||
{
|
||||
koSettleDate = KOObsSettleDates[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (tradeSnowball.KORebateType == RebateTypeEnum.AtEnd)
|
||||
{
|
||||
koSettleDate = otcTrade.ExerciseDate.Value;
|
||||
}
|
||||
else if (koSettleDate < valueDate)
|
||||
{
|
||||
koSettleDate = valueDate;
|
||||
}
|
||||
|
||||
if (otcTrade.IsMoneynessOptionData)
|
||||
{
|
||||
koBarrier *= otcTrade.SpotPrice ?? 1.0;
|
||||
}
|
||||
|
||||
return (koSettleDate, koBarrier);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user