从山证v2.3.0拷贝
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
using BaseOUDAL;
|
||||
using YLErp.Modules.CalculationModule;
|
||||
using YLErp.Modules.SkewMapVolModule;
|
||||
using YLErp.QdpModule;
|
||||
using YLErp.QdpModule.Constants;
|
||||
|
||||
namespace YLErp.Modules.VolatilityModule
|
||||
{
|
||||
/// <summary>
|
||||
/// 波动率取值服务
|
||||
/// </summary>
|
||||
public class SingleVolService
|
||||
{
|
||||
public static double GetSingleVol(SingleVolReq singleVolReq, int userId, bool isEodCalc = false)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(singleVolReq.VolType))
|
||||
{
|
||||
throw new ServiceException("波动率类型不能为空");
|
||||
}
|
||||
|
||||
if (singleVolReq.ExerciseDate == DateTime.MinValue)
|
||||
{
|
||||
throw new ServiceException("行权日不能为空");
|
||||
}
|
||||
|
||||
if (singleVolReq.TradeDate == DateTime.MinValue)
|
||||
{
|
||||
throw new ServiceException("交易日期不能为空");
|
||||
}
|
||||
|
||||
if (PS.Config.ErpElement.SkewMapVolConstruction)
|
||||
{
|
||||
return GetSingleVolWithSkewMapMode(singleVolReq, userId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetSingleVolWithNormalMode(singleVolReq, userId, isEodCalc);
|
||||
}
|
||||
}
|
||||
|
||||
//获取正常模式的波动率
|
||||
private static double GetSingleVolWithNormalMode(SingleVolReq singleVolReq, int userId, bool isEodCalc = false)
|
||||
{
|
||||
var userGroup = singleVolReq.UserGroup.TrimToNull() ?? UserBLL.GetUserGroup(userId);
|
||||
var volatility = new VolatilityQueryService(OptUserInfo.SystemUser)
|
||||
.GetVolatility(userGroup, singleVolReq.TradeDate, singleVolReq.VolType, singleVolReq.UnderlyingCode);
|
||||
if (volatility == null)
|
||||
{
|
||||
throw new ServiceException($"没有找到{singleVolReq.VolType}波动率数据:{singleVolReq.UnderlyingCode}");
|
||||
}
|
||||
if (volatility is VolatilityDefault)
|
||||
{
|
||||
return ConsVolInfos.defVol;
|
||||
}
|
||||
var req = new InterpolatedVolReq
|
||||
{
|
||||
valueDate = singleVolReq.TradeDate,
|
||||
exerciseDate = singleVolReq.ExerciseDate,
|
||||
strike = singleVolReq.Strike,
|
||||
isMoneynessOption = singleVolReq.IsMoneynessOption == "是",
|
||||
isEodCalc = isEodCalc,
|
||||
spot = singleVolReq.SpotPrice,
|
||||
volSurfaceType = volatility.VolSurfaceMode
|
||||
};
|
||||
return QdpVolHelper.GetInterpolatedVolFromNormalSurface(volatility.VolTable, req, volatility.InterpolationMethod);
|
||||
}
|
||||
|
||||
//获取skew模式的波动率
|
||||
private static double GetSingleVolWithSkewMapMode(SingleVolReq req, int userId)
|
||||
{
|
||||
if (req.Vols == null)
|
||||
{
|
||||
var userGroup = UserBLL.GetUserGroup(userId);
|
||||
req.Vols = new VolatilityQueryService(OptUserInfo.SystemUser)
|
||||
.GetVolatility(userGroup, req.TradeDate, "交易", req.UnderlyingCode);
|
||||
}
|
||||
|
||||
if (req.Vols == null || string.IsNullOrEmpty(req.Vols.VolSurfaceMode))
|
||||
{
|
||||
throw new InvalidOperationException($"找不到波动率曲面{req.UnderlyingCode}");
|
||||
}
|
||||
|
||||
if (!req.BaseVol.HasValue)
|
||||
{
|
||||
throw new InvalidOperationException($"参数BaseVol缺失");
|
||||
}
|
||||
|
||||
//var initParam = new VolSurfaceInitParamsBuilder(userId.ToString()).SetValueDate(singleVolReq.TradeDate)
|
||||
// .SetUnderlying(singleVolReq.UnderlyingId, singleVolReq.UnderlyingCode, singleVolReq.UnderlyingName).SetVolatility(volatility).Build();
|
||||
|
||||
//VolSurfaceInitializerSingleton.GetInitializer(false).InitializeMarketProxy(initParam);
|
||||
|
||||
if (req.VolType == "报价Bid")
|
||||
{
|
||||
if (!req.BidVar.HasValue || req.BidVar.Value < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
//var marketProxy = QdpMarketManager.Instance.GetPrebuiltMarketProxy(userId.ToString());
|
||||
var baseVolSurface = SkewMapVolHelper.GetSkewMapBaseVolSurface(req.UnderlyingCode, req.Vols);
|
||||
var skewMapVolSurface = new SkewMapVolSurface(baseVolSurface.BaseVol);
|
||||
|
||||
var t = TradeCalcHelper.CalculateTTMDays(
|
||||
req.TradeDate,
|
||||
req.ExerciseDate,
|
||||
req.UnderlyingTypeId,
|
||||
precisionOfMinute: false);
|
||||
|
||||
return skewMapVolSurface.GetVolWithBaseVol(
|
||||
baseVol: req.BaseVol.Value,
|
||||
t: Math.Ceiling(t), //不考虑日内精确时间
|
||||
k: req.Strike,
|
||||
spot: req.SpotPrice,
|
||||
isCall: req.CallPut == "Call",
|
||||
isBuy: true,
|
||||
var: req.BidVar ?? 0);
|
||||
}
|
||||
else if (req.VolType == "报价Ask")
|
||||
{
|
||||
if (!req.AskVar.HasValue || req.AskVar.Value < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//var marketProxy = QdpMarketManager.Instance.GetPrebuiltMarketProxy(userId.ToString());
|
||||
var baseVolSurface = SkewMapVolHelper.GetSkewMapBaseVolSurface(req.UnderlyingCode, req.Vols);
|
||||
var skewMapVolSurface = new SkewMapVolSurface(baseVolSurface.BaseVol);
|
||||
|
||||
var t = TradeCalcHelper.CalculateTTMDays(
|
||||
req.TradeDate,
|
||||
req.ExerciseDate,
|
||||
req.UnderlyingTypeId,
|
||||
precisionOfMinute: false);
|
||||
|
||||
return skewMapVolSurface.GetVolWithBaseVol(
|
||||
baseVol: req.BaseVol.Value,
|
||||
t: Math.Ceiling(t), //不考虑日内精确时间
|
||||
k: req.Strike,
|
||||
spot: req.SpotPrice,
|
||||
isCall: req.CallPut == "Call",
|
||||
isBuy: false,
|
||||
var: req.AskVar ?? 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("波动率类型应为'报价Bid'或'报价Ask'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user