130 lines
5.3 KiB
C#
130 lines
5.3 KiB
C#
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<autocall_observation> 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<autocall_observation>()
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|