228 lines
8.0 KiB
C#
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; }
|
|
}
|
|
}
|
|
}
|