从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
using Qdp.Foundation.Implementations;
|
||||
using Qdp.Pricing.Base.Implementations;
|
||||
using Qdp.Pricing.Base.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using YLErp.Abstract;
|
||||
using YLErp.BLL.Eod;
|
||||
using YLErp.BLL;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Modules.TradeModule.KnockOutModule.Dto;
|
||||
using YLErp.QdpModule;
|
||||
|
||||
namespace YLErp.Modules.TradeModule.KnockOutModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 障碍期权敲出服务
|
||||
/// </summary>
|
||||
public class BarrierOptionTradeKnockOutService : ITradeKnockOutService
|
||||
{
|
||||
public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate, ITradeExtendDataProvider _tradeExtendDataProvider)
|
||||
{
|
||||
GetKnockOutPayoffResult result = new GetKnockOutPayoffResult { IsKnockOut = false };
|
||||
|
||||
var barrierOption = _tradeExtendDataProvider.GetTrade_Barrier_Option(td.id);
|
||||
if (barrierOption == null)
|
||||
{
|
||||
return new GetKnockOutPayoffResult { IsKnockOut = false };
|
||||
}
|
||||
td.trade_barrier_option = barrierOption;
|
||||
return GetKnockOutPayoff(td, underlyingPrice, _valueDate);
|
||||
}
|
||||
|
||||
public GetKnockOutPayoffResult GetKnockOutPayoff(trade td, double underlyingPrice, DateTime _valueDate)
|
||||
{
|
||||
GetKnockOutPayoffResult result = new GetKnockOutPayoffResult { IsKnockOut = false };
|
||||
var barrierOption = td.trade_barrier_option;
|
||||
if (barrierOption == null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
//连续每天观察 离散根据观察日判断 如果非观察日 不检测敲入敲出
|
||||
if ("离散".Equals(barrierOption.Discrete))
|
||||
{
|
||||
var observationDates = QdpHelper.GetObservationDatesFromString(barrierOption.ObservationDates);
|
||||
//每日观察或者当前结算日是观察日的时候,才检查是否会敲入敲出
|
||||
if (observationDates != null && observationDates.Length > 0 && !observationDates.Contains(_valueDate))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
var BarrierPrice = td.IsMoneynessOptionData ? barrierOption.BarrierPrice * td.SpotPrice : barrierOption.BarrierPrice;
|
||||
var UpperBarrierPrice = td.IsMoneynessOptionData ? barrierOption.UpperBarrierPrice * td.SpotPrice : barrierOption.UpperBarrierPrice;
|
||||
switch (barrierOption.BarrierType)
|
||||
{
|
||||
case "上升敲出":
|
||||
if (underlyingPrice >= BarrierPrice)
|
||||
{
|
||||
result.IsKnockOut = true;
|
||||
result.Payoff = CalcBarrierOptionTradeKnockOutPayoff(td, barrierOption, underlyingPrice, _valueDate);
|
||||
}
|
||||
break;
|
||||
case "下降敲出":
|
||||
if (underlyingPrice <= BarrierPrice)
|
||||
{
|
||||
result.IsKnockOut = true;
|
||||
result.Payoff = CalcBarrierOptionTradeKnockOutPayoff(td, barrierOption, underlyingPrice, _valueDate);
|
||||
}
|
||||
break;
|
||||
case "双障碍敲出":
|
||||
if (underlyingPrice >= UpperBarrierPrice || underlyingPrice <= BarrierPrice)
|
||||
{
|
||||
result.IsKnockOut = true;
|
||||
var upDown = underlyingPrice >= UpperBarrierPrice ? true : false;
|
||||
result.Payoff = CalcBarrierOptionTradeKnockOutPayoff(td, barrierOption, underlyingPrice, _valueDate, upDown);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算具体收益
|
||||
/// </summary>
|
||||
/// <param name="td"></param>
|
||||
/// <param name="barrierOption"></param>
|
||||
/// <param name="underlyingPrice"></param>
|
||||
/// <param name="upDown">双障碍敲出 才有用</param>
|
||||
/// <returns></returns>
|
||||
private double CalcBarrierOptionTradeKnockOutPayoff(trade td, trade_barrier_option barrierOption, double underlyingPrice,DateTime _valueDate, bool upDown = false)
|
||||
{
|
||||
var spotPrice = td.SpotPrice ?? 0;
|
||||
|
||||
double rebate, rebateRate; //计算补偿金额
|
||||
if (upDown)
|
||||
{
|
||||
if (td.IsUsePremiumRate == true)
|
||||
{
|
||||
rebateRate = barrierOption.RebateHighRate ?? 0;
|
||||
rebate = rebateRate * spotPrice;
|
||||
}
|
||||
else
|
||||
{
|
||||
rebate = barrierOption.RebateHigh ?? 0;
|
||||
rebateRate = spotPrice > 0 ? rebate / spotPrice : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (td.IsUsePremiumRate == true)
|
||||
{
|
||||
rebateRate = barrierOption.RebateRate ?? 0;
|
||||
rebate = rebateRate * spotPrice;
|
||||
}
|
||||
else
|
||||
{
|
||||
rebate = barrierOption.Rebate ?? 0; //补偿金额
|
||||
rebateRate = spotPrice > 0 ? rebate / spotPrice : 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (barrierOption.RebateAnnualizedAtKO) //补偿按敲出日年化
|
||||
{
|
||||
var rebateDayCountImpl = string.IsNullOrWhiteSpace(barrierOption.RebateDayCount) ? new Act365() : barrierOption.RebateDayCount.ToDayCountImpl();
|
||||
var fraction = rebateDayCountImpl.CalcDayCountFraction(new Date(td.StartDate.Value), new Date(_valueDate));
|
||||
rebate *= fraction;
|
||||
rebate += Math.Abs((td.TradeSinglePrice - td.TradeSinglePrice * fraction) ?? 0);
|
||||
}
|
||||
|
||||
var payoff = td.Notional * rebate + ((td.Notional / td.OriginalNotional * td.OriginalPrincipalSum) ?? 0); // 补偿金额 * 持仓份额 + 保底收益总额*尺长比例
|
||||
|
||||
//交易员视角
|
||||
if (valuedateBLL.SystemDate.UnwindAmountAngle == 1)
|
||||
{
|
||||
payoff = payoff * (td.BuySell == "卖出" ? -1 : 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
payoff = payoff * EodOperationBase.GetSign(td.BuySell);
|
||||
}
|
||||
return payoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user