using Qdp.Pricing.Library.Common.MathMethods.VolTermStructure;
using YLErp.Abstract;
using YLErp.Models;
using YLErp.Modules.SkewMapVolModule;
using YLErp.QdpModule;
using YLErp.QdpModule.Constants;
namespace YLErp.Modules.CalculationModule
{
public static class SkewMapVolHelper
{
public static double GetInterpolatedVol(
IVolatility volSurface,
DateTime valueDate,
string underlyingCode,
DateTime exerciseDate,
double strikePrice,
bool isBuy,
bool isCall,
double spotPrice,
double timeToMaturityDays = double.NaN,
int? skewMapVolVar = null)
{
var baseVolSurface = GetSkewMapBaseVolSurface(underlyingCode, volSurface);
var skewMapVolSurface = new SkewMapVolSurface(baseVolSurface.BaseVol);
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
var t = double.IsNaN(timeToMaturityDays)
? TradeCalcHelper.CalculateTTMDays(
valueDate,
exerciseDate,
varietyid: underlying?.UnderlyingTypeId ?? 0,
precisionOfMinute: false)
: timeToMaturityDays;
var volVar = skewMapVolVar ?? (int)(isBuy ? baseVolSurface.BidVar : baseVolSurface.AskVar);
return skewMapVolSurface.GetVol(
t: Math.Ceiling(t), //不考虑日内精确时间
k: strikePrice,
spot: spotPrice,
isCall: isCall,
isBuy: isBuy,
var: volVar);
}
///
/// skewmapvol转换为正常波动率构造
///
public static IVolatility GetNormalVolatility(
IVolatility volSurface,
DateTime valueDate,
string underlyingCode,
DateTime exerciseDate,
double strikePrice,
bool isBuy,
bool isCall,
double spotPrice,
double timeToMaturityDays = double.NaN,
int? skewMapVolVar = null)
{
var vol = GetInterpolatedVol(volSurface, valueDate, underlyingCode, exerciseDate, strikePrice, isBuy, isCall, spotPrice, timeToMaturityDays, skewMapVolVar);
var singleVols = QdpVolHelper.GenerateFlatSingleVols(vol);
return new VolatilityImpl
{
InterpolationMethod = ConsVolInfos.defInterpolationMethod,
VolSurfaceMode = ConsVolInfos.defVolMode,
VolTable = singleVols
};
}
public static SkewMapBaseVolSurface GetSkewMapBaseVolSurface(string underlyingCode, IVolatility volSurface)
{
Dictionary baseVols = null;
try
{
baseVols = volSurface.VolTable.ToDictionary(x => x.Expire, x => x.Vol);
}
catch (Exception ex)
{
throw new Exception($"{underlyingCode}的BaseVol格式不正确", ex);
}
if (baseVols == null)
{
throw new Exception($"{underlyingCode}的BaseVol为空");
}
if (!baseVols.ContainsKey("BidVar") || !baseVols.ContainsKey("AskVar"))
{
throw new Exception($"{underlyingCode}的BidVar或AskVar缺失");
}
var baseVolSurface = new SkewMapBaseVolSurface
{
BaseVol = baseVols,
BidVar = baseVols["BidVar"],
AskVar = baseVols["AskVar"]
};
return baseVolSurface;
}
///
/// 获取某交易的BaseVol
///
public static double GetSkewMapBaseVolForTrade(
DateTime valueDate,
string UnderlyingCode,
IVolatility volSurface,
int UnderlyingTypeId,
DateTime ExerciseDate,
double timeToMaturityDays = double.NaN)
{
var baseVolSurface = GetSkewMapBaseVolSurface(UnderlyingCode, volSurface);
var skewMapVolSurface = new SkewMapVolSurface(baseVolSurface.BaseVol);
var t = double.IsNaN(timeToMaturityDays)
? TradeCalcHelper.CalculateTTMDays(
valueDate,
ExerciseDate,
UnderlyingTypeId,
precisionOfMinute: false)
: timeToMaturityDays;
//用于波动率插值的t,不考虑日内精确时间,所以向上取整
return skewMapVolSurface.GetBaseVol(Math.Ceiling(t));
}
public static List ContructSkewMapVolTable(double baseVol, int bidVar, int askVar)
{
return new List()
{
new SingleVol()
{
Strike = 1.0,
Expire = "1M",
Vol = baseVol
},
new SingleVol()
{
Strike = 1.0,
Expire = "3M",
Vol = baseVol
},
new SingleVol()
{
Strike = 1.0,
Expire = "6M",
Vol = baseVol
},
new SingleVol()
{
Strike = 1.0,
Expire = "BidVar",
Vol = bidVar
},
new SingleVol()
{
Strike = 1.0,
Expire = "AskVar",
Vol = askVar
},
};
}
}
}