Files
zszq-trs/YLErpDAL/Modules/CalculationModule/ImpliedVolCalcService.cs
T
2024-05-09 14:06:26 +08:00

140 lines
5.8 KiB
C#

using Qdp.ComputeService.Data.CommonModels.ValuationParams.Equity;
using Qdp.Foundation.Implementations;
using YLErp.Abstract;
using YLErp.BLL.Calculation;
using YLErp.QdpModule;
namespace YLErp.Modules.CalculationModule
{
/// <summary>
/// 隐含波动率计算服务
/// </summary>
public class ImpliedVolCalcService
{
/// <summary>
/// 根据权利金计算隐含波动率
/// </summary>
/// <param name="premium">期权单价</param>
/// <param name="valueDate">计算日期</param>
public static double ImpliedVolFromPremium(
double premium,
DateTime valueDate,
string underlyingTicker,
string underlyingInstrumentType,
double strike,
DateTime startDate,
DateTime endDate,
string optionType,
string exerciseType,
double spotPrice,
double notional,
double riskFreeRate,
string tradeType,
DateTime exerciseDate,
double participationRate,
double principalRate,
bool isAnnualized,
double annualizeFactor,
double dividendRate = 0.0,
bool isMoneynessOption = false,
double initialSpotPrice = 0.0,
Dictionary<Date, double> dividends = null,
bool hasNightMarket = false,
bool preciseTimeMode = false,
double ttmDays = double.NaN, IVolatility volatility = null)
{
var optionTradeParam = new VanillaOptionTradeParam
{
annualizedFactor = annualizeFactor,
buysell = tradeType,
preciseTimeMode = preciseTimeMode,
dividendRate = dividendRate,
dividends = dividends,
endDate = endDate,
exerciseDate = exerciseDate,
exerciseType = exerciseType,
hasNightMarket = hasNightMarket,
initialSpotPrice = initialSpotPrice,
isAnnualized = isAnnualized,
isMoneynessOption = isMoneynessOption,
notional = notional,
optionType = QdpConverter.ConvertOptionType(optionType),
participationRate = participationRate,
principalRate = principalRate,
riskFreeRate = riskFreeRate,
settlementDate = exerciseDate,
startDate = startDate,
strike = strike,
timeToMaturityDays = ttmDays,
tradeDate = startDate,
underlyingInstrumentType = underlyingInstrumentType,
underlyingTickers = new[] { underlyingTicker },
tradeId = null,
volSurfaceNames = null,
isForwardTrade = false
};
return ImpliedVolFromPremium(premium, valueDate, optionTradeParam, spotPrice, volatility);
}
/// <summary>
/// 根据权利金计算隐含波动率
/// </summary>
/// <param name="premium">期权单价</param>
/// <param name="valueDate">计算日期</param>
/// <param name="optionTradeParam">期权要素</param>
/// <param name="spotPrice">标的现价</param>
public static double ImpliedVolFromPremium(double premium, DateTime valueDate
, VanillaOptionTradeParam optionTradeParam, double spotPrice, IVolatility volatility = null)
{
//在计算ImpliedVol时,提前处理strike,然后都当做非MoneynessOption处理
if (optionTradeParam.isMoneynessOption)
{
optionTradeParam.isMoneynessOption = false;
optionTradeParam.strike *= optionTradeParam.initialSpotPrice;
}
if (optionTradeParam.volSurfaceNames == null || !optionTradeParam.volSurfaceNames.Any())
{
optionTradeParam.volSurfaceNames = new[] { Guid.NewGuid().ToString() };
}
var volSurfaceName = optionTradeParam.volSurfaceNames[0];
if (optionTradeParam.underlyingTickers == null || !optionTradeParam.underlyingTickers.Any())
{
throw new Exception("缺少标的代码");
}
var underlyingTicker = optionTradeParam.underlyingTickers[0];
optionTradeParam.buysell = "买入";
var optionTrade = QdpTradeBuilder.GetVanillaOptionTrade(optionTradeParam);
using (var marketProxy = new MarketProxy(valueDate, optionTradeParam.riskFreeRate))
{
//设置标的价格
marketProxy.SetStockPrice(underlyingTicker, spotPrice);
marketProxy.SetVolSurface(volSurfaceName, volatility ?? QdpVolHelper.GetDefaultVolatility(0.3));
OptionValuationParameters parameters;
if (optionTradeParam.underlyingInstrumentType == ConsGlobal.InstrumentType.Stock)
{
//设置DividendCurve
var dividendCurveName = Guid.NewGuid().ToString();
var dividendCurve = CalculatorHelper.CreateConstantRiskFreeCurve(dividendCurveName, optionTradeParam.dividendRate);
marketProxy.SetYieldCurve(dividendCurveName, dividendCurve);
parameters = new OptionValuationParameters(marketProxy.DiscountCurveName, dividendCurveName, volSurfaceName, underlyingTicker);
}
else
{
parameters = new OptionValuationParameters(marketProxy.DiscountCurveName, MarketProxy.ConstantZeroCurve, volSurfaceName, underlyingTicker);
}
return optionTrade.ImpliedVolFromPremium(premium, marketProxy.QdpMarket, parameters);
}
}
}
}