using Newtonsoft.Json; using YLErp.DBModels.Consts; using YLErp.Models; using YLErp.QdpModule.Constants; namespace YLErp.Modules.VolatilityModule.ApiModule { /// /// 曲面波动率提供(用于API服务) /// public partial class UnderlyingVolServiceV2 : YLBaseService { public UnderlyingVolServiceV2(OptUserInfo userInfo) : base(userInfo) { } /// /// API获取波动率 /// public IEnumerable 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>(item.VolTableJson); } } return vols; } /// /// API保存波动率 /// 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 { 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; } } } }