using BaseOUDAL;
using System.Text.RegularExpressions;
using YLErp.Modules.CalculationModule;
namespace YLErp.Modules.VolatilityModule.SkewMapVolModule
{
///
/// 从数据库中查询SkewVol
///
public class SkewVolQueryService
{
public static volatility GetVol(int userId, SkewVolRequest req)
{
if (req is null)
{
throw new ArgumentNullException(nameof(req));
}
if (string.IsNullOrWhiteSpace(req.VolType))
{
throw new Exception("波动率类型不能为空");
}
var userGroup = UserBLL.GetUserGroup(userId);
var vols = VolatilityHelper.GetVol(req.valueDate, "交易", req.UnderlyingCode, userGroup);
if (vols == null || string.IsNullOrEmpty(vols.VolSurfaceMode))
{
throw new InvalidOperationException($"找不到波动率曲面{req.UnderlyingCode}");
}
var singleVols = vols.VolTable;
for (var i = 0; i < singleVols.Count; i++)
{
if (!Regex.IsMatch(singleVols[i].Expire, @"\d")) { continue; }
var ExerciseDate = GetExerciseDate(req.valueDate, singleVols[i].Expire);
singleVols[i].Vol = SkewMapVolHelper.GetInterpolatedVol(
volSurface: vols,
valueDate: req.valueDate,
underlyingCode: req.UnderlyingCode,
exerciseDate: ExerciseDate,
strikePrice: req.Strike,
isBuy: req.VolType == "报价Bid",
isCall: false,
spotPrice: req.Strike,
skewMapVolVar: (int)(req.VolType == "报价Bid" ? vols.GetBidVar() : vols.GetAskVar())
);
}
vols.Data = singleVols.ToJson();
return vols;
}
private static DateTime GetExerciseDate(DateTime valueDate, string term)
{
var result = valueDate;
var m = Regex.Match(term, @"^(?\d+)(?[D|W|M|Y])$");
if (!m.Success) { return result; }
var number = int.Parse(m.Groups["num"].Value);
switch (m.Groups["unit"].Value)
{
case "D":
result = result.AddDays(number);
break;
case "W":
result = result.AddDays(number * 7);
break;
case "M":
result = result.AddMonths(number).AddDays(-1);
break;
case "Y":
result = result.AddYears(number).AddDays(-1);
break;
}
return result;
}
}
public class SkewVolRequest
{
public DateTime valueDate { get; set; }
public string VolType { get; set; }
public string UnderlyingCode { get; set; }
public double Strike { get; set; }
}
}