从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using YLErp.DBModels.Consts;
|
||||
using YLErp.Modules.CalculationModule;
|
||||
using YLErp.QdpModule;
|
||||
|
||||
namespace YLErp.Modules.EodModule.SettlementModule.V2
|
||||
{
|
||||
/// <summary>
|
||||
/// 临时存放
|
||||
/// </summary>
|
||||
class EodPositionSettleServiceTemp<TRisk, TPosition, TPnl> : EodSettleServiceBaseV2
|
||||
where TPnl : EodPnl, new()
|
||||
where TRisk : EodTradeRisk, new()
|
||||
where TPosition : EodTradePosition, new()
|
||||
{
|
||||
public EodPositionSettleServiceTemp(EodSettlementContextV2 context) : base(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#region----盈亏分解V1----
|
||||
|
||||
//判断是否可以进行盈亏分解计算
|
||||
private bool CanCalcPnlExplain(OtcTradeBase td)
|
||||
{
|
||||
switch (td.TradeType)
|
||||
{
|
||||
case "远期":
|
||||
case "收益互换":
|
||||
case "自定义交易":
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalcPnlExplainV1(trade td, TPnl pnl1, TRisk risk1, double spotPrice1, double riskFreeRate1)
|
||||
{
|
||||
if (!CanCalcPnlExplain(td))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var preRisk = DbContext.Set<TRisk>().Where(n => n.ValueDate < _context.SettleDate && n.TradeId == td.id)
|
||||
.OrderByDescending(n => n.ValueDate).Select(n => new { n.ValueDate, n.Vol, n.Pv }).FirstOrDefault();
|
||||
|
||||
if (preRisk == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DateTime date0;
|
||||
|
||||
double spotPrice0, vol0, riskFreeRate0, PV0, vol1 = risk1.Vol;
|
||||
|
||||
var hisData = DbContext.TradeHisData.Where(n => n.TradeId == td.id && n.ValueDate < _context.SettleDate && n.ValueType == ConsTradeField.NoRiskRate)
|
||||
.OrderByDescending(n => n.ValueDate).Select(n => new { n.Value }).FirstOrDefault();
|
||||
|
||||
spotPrice0 = _context.GetPreEodPriceProvider().GetPrice(td.UnderlyingCode, td.SettlementType);
|
||||
|
||||
PV0 = preRisk.Pv;
|
||||
vol0 = preRisk.Vol;
|
||||
date0 = preRisk.ValueDate;
|
||||
|
||||
riskFreeRate0 = hisData?.Value ?? td.NoRiskRate ?? riskFreeRate1;
|
||||
|
||||
var sdiff = spotPrice1 - spotPrice0;
|
||||
pnl1.PnLDelta = risk1.Delta * sdiff;
|
||||
pnl1.PnLGamma = risk1.Gamma * sdiff * sdiff / 2;
|
||||
pnl1.PnLVega = risk1.Vega * (risk1.Vol - vol0) * 100;
|
||||
pnl1.PnLTheta = risk1.Theta * (_context.SettleDate - _context.PreSettleDate).TotalDays;
|
||||
pnl1.PnLRho = risk1.Rho * (riskFreeRate1 - riskFreeRate0);
|
||||
|
||||
//交易在上一交易日使用当前交易日的标的价格计算出的Pv
|
||||
var PV0s1 = CalcPnlExplainV1(td, date0, spotPrice1, vol0, riskFreeRate0);
|
||||
|
||||
//交易在上一交易日使用当前交易日的波动率计算出的Pv
|
||||
var PV0v1 = CalcPnlExplainV1(td, date0, spotPrice0, vol1, riskFreeRate0);
|
||||
|
||||
//交易在上一交易日使用当前交易日的标的价格和波动率计算出的Pv
|
||||
var PV0s1v1 = CalcPnlExplainV1(td, date0, spotPrice1, vol1, riskFreeRate0);
|
||||
|
||||
pnl1.PnLPrice = PV0s1 - PV0;
|
||||
pnl1.PnLVol = PV0v1 - PV0;
|
||||
pnl1.PnLPriceVolCross = PV0s1v1 - PV0 - pnl1.PnLPrice - pnl1.PnLVol;
|
||||
}
|
||||
|
||||
private static double CalcPnlExplainV1(trade td, DateTime valueDate, double spotPrice, double vol, double riskFreeRate)
|
||||
{
|
||||
var req = new OptionValueCalcRequest(riskFreeRate)
|
||||
{
|
||||
correlations = null,//不计算彩虹等多标的期权暂时不需要
|
||||
engineName = null,
|
||||
preciseTimeMode = false, //日终一定是false
|
||||
isEodCalc = true,
|
||||
pricingRequest = QdpPricingRequest.PV_ONLY,
|
||||
spotPrices = new[] { spotPrice },
|
||||
vols = new[] { vol }
|
||||
};
|
||||
|
||||
var result = OptionCalculatorV2.GetOptionValueResult(valueDate, td, req, out _);
|
||||
|
||||
return NumberHelper.Normalize(result.Pv);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user