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

228 lines
8.0 KiB
C#

using Newtonsoft.Json;
using YLErp.DBModels.Consts;
using YLErp.Models;
using YLErp.QdpModule.Constants;
namespace YLErp.Modules.VolatilityModule.ApiModule
{
/// <summary>
/// 曲面波动率提供(用于API服务)
/// </summary>
public partial class UnderlyingVolServiceV2 : YLBaseService
{
public UnderlyingVolServiceV2(OptUserInfo userInfo) : base(userInfo)
{
}
/// <summary>
/// API获取波动率
/// </summary>
public IEnumerable<UnderlyingVolQueryApiResultV2> GetVolSurfaces(UnderlyingVolQueryApiRequestV2 request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (request.VolTypes == null || !request.VolTypes.Any())
{
throw new ArgumentException("VolTypes不能为空", nameof(request.VolTypes));
}
if (request.UnderlyingCodes == null || !request.UnderlyingCodes.Any())
{
throw new ArgumentException("UnderlyingCodes不能为空", nameof(request.UnderlyingCodes));
}
if (!ConsUserGroup.HasGroup)
{
request.UserGroup = string.Empty;
}
else if (string.IsNullOrWhiteSpace(request.UserGroup))
{
throw new ArgumentException("UserGroup不能为空", nameof(request.UserGroup));
}
request.ValueDate = request.ValueDate.Date;
if (request.ValueDate.Year < 1949)
{
throw new ArgumentException("ValueDate填写不正确:" + request.ValueDate, nameof(request.ValueDate));
}
//数据量小的表尽量靠前
var groupQuery = from v in DbContext.volatility
where v.QuotationDate <= request.ValueDate
&& request.VolTypes.Contains(v.VolType)
&& request.UnderlyingCodes.Contains(v.ContractCode)
&& v.UserGroup == request.UserGroup
group v by new { v.UserGroup, v.ContractCode, v.VolType } into vg
select new
{
vg.Key.UserGroup,
vg.Key.ContractCode,
vg.Key.VolType,
QuotationDate = vg.Max(n => n.QuotationDate)
};
var volQuery = from vg in groupQuery
join v in DbContext.volatility
on vg equals new { v.UserGroup, v.ContractCode, v.VolType, v.QuotationDate }
orderby v.ContractCode
select new UnderlyingVolQueryApiResultV2
{
VolType = v.VolType,
InnerQuotationDate = v.QuotationDate,
UnderlyingCode = v.ContractCode,
VolTableJson = v.Data
};
var vols = volQuery.ToArray();
foreach (var item in vols)
{
if (!string.IsNullOrWhiteSpace(item.VolTableJson))
{
item.VolTable = JsonConvert.DeserializeObject<List<SingleVol>>(item.VolTableJson);
}
}
return vols;
}
/// <summary>
/// API保存波动率
/// </summary>
public volatility SaveVolSurface(UnderlyingVolSaveApiRequestV2 request)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
if (string.IsNullOrEmpty(request.ContractCode))
{
throw new ServiceException("标的代码 必须填写");
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(request.ContractCode);
if (underlying == null)
{
throw new ServiceException("标的信息未存在:" + request.ContractCode);
}
if (string.IsNullOrEmpty(request.VolType))
{
throw new ServiceException("波动率类型 必须填写");
}
request.ValueDate = request.ValueDate.Date;
if (request.ValueDate.Year < 1949)
{
throw new ServiceException("ValueDate填写不正确:" + request.ValueDate);
}
if (request.VolTable?.Any() != true)
{
throw new ServiceException("缺少VolTable");
}
if (string.IsNullOrEmpty(request.InterpolationMethod))
{
request.InterpolationMethod = ConsVolInfos.defInterpolationMethod;
}
if (!ConsUserGroup.HasGroup)
{
request.UserGroup = string.Empty;
}
else if (string.IsNullOrWhiteSpace(request.UserGroup))
{
throw new ArgumentException("UserGroup不能为空", nameof(request.UserGroup));
}
volatility retVol = null;
var underlyingList = new List<InnerUnderlying> {
new InnerUnderlying{ UnderlyingId = underlying.id,UnderlyingCode = underlying.UnderlyingCode}
};
//波动率上传 以连续合约 覆盖所有标的的 麻烦尽快实现
if (request.OverridByMainCode)
{
int underlyingTypeId = 0;
if (System.Text.RegularExpressions.Regex.IsMatch(request.ContractCode, "^[a-zA-Z]+00$"))
{
var un = DataCacheProvider.GetUnderlyingDataSource().GetData(request.ContractCode);
if (un?.IsFutures() == true && un.UnderlyingTypeId > 0)
{
underlyingTypeId = un.UnderlyingTypeId;
}
}
if (underlyingTypeId > 0)
{
var query = from un in DbContext.underlying_manager
where un.UnderlyingTypeId == underlyingTypeId
&& (un.MaturityDate >= request.QuotationDate)
&& un.UnderlyingCode != request.ContractCode
select new InnerUnderlying
{
UnderlyingId = un.id,
UnderlyingCode = un.UnderlyingCode
};
underlyingList.AddRange(query.ToArray());
}
}
foreach (var un in underlyingList)
{
var dbVol = DbContext.volatility.FirstOrDefault(n => n.QuotationDate == request.ValueDate
&& n.ContractCode == un.UnderlyingCode && n.VolType == request.VolType && n.UserGroup == request.UserGroup);
if (dbVol == null)
{
dbVol = new volatility
{
UnderlyingId = un.UnderlyingId,
ContractCode = un.UnderlyingCode,
VolType = request.VolType,
UserGroup = request.UserGroup,
QuotationDate = request.ValueDate,
VolSurfaceMode = ConsVolInfos.defVolMode
};
DbContext.volatility.Add(dbVol);
}
dbVol.SetOpt(OptUser);
dbVol.SetData(request.VolTable);
dbVol.InterpolationMethod = request.InterpolationMethod;
if (retVol == null)
{
retVol = dbVol;
}
}
DbContext.SaveChanges();
return retVol;
}
class InnerUnderlying
{
public int UnderlyingId { get; set; }
public string UnderlyingCode { get; set; }
}
}
}