namespace YLErp.Modules.VolatilityModule { /// /// 品种波动率数据服务 /// public class VarietyVolService : YLBaseService { public VarietyVolService(OptUserInfo userInfo) : base(userInfo) { } public VarietyVolService(YLBaseService baseService) : base(baseService) { } /// /// 获取距valueDate最近的品种波动率 /// public VarietyVol GetVol(long varietyId, DateTime valueDate) { var query = from volDb in DbContext.variety_vol where volDb.VarietyId == varietyId && volDb.ValueDate <= valueDate orderby volDb.ValueDate descending select volDb; return query.FirstOrDefault(); } /// /// 获取距date最近的品种波动率 /// public List GetVols(DateTime date, IEnumerable varietyIds) { if (varietyIds is null) { throw new ArgumentNullException(nameof(varietyIds)); } var idSet = varietyIds.ToHashSet(); var grpQry = from vol in DbContext.variety_vol where vol.ValueDate <= date && idSet.Contains(vol.VarietyId) group vol by vol.VarietyId into grp select new { VarietyId = grp.Key, ValueDate = grp.Max(n => n.ValueDate) }; var qry = from gv in grpQry join vol in DbContext.variety_vol on gv equals new { vol.VarietyId, vol.ValueDate } orderby gv.VarietyId select new VarietyVolDto { VarietyId = vol.VarietyId, ValueDate = vol.ValueDate, Vol = vol.Vol }; var list = qry.ToList(); foreach (var data in list) { idSet.Remove(data.VarietyId); } var defArr = idSet.Select(n => new VarietyVolDto { VarietyId = n, ValueDate = date, Vol = ConsGlobal.DefaultVol }).ToArray(); list.AddRange(defArr); return list; } /// /// 保存数据 /// public void SaveData(int varietyId, DateTime valueDate, double vol) { if (varietyId == default) { throw new ArgumentNullException("varietyId"); } if (valueDate == default) { throw new ArgumentNullException("valueDate"); } if (vol == default(int)) { throw new ArgumentNullException("vol"); } if (!DbContext.variety.Any(n => n.id == varietyId)) { throw new ServiceException("品种不存在"); } var dbModel = DbContext.variety_vol.FirstOrDefault(n => n.VarietyId == varietyId && n.ValueDate == valueDate); if (dbModel == null) { DbContext.variety_vol.Add(new VarietyVol { ValueDate = valueDate, VarietyId = varietyId, Vol = vol, OptDate = DateTime.Now, OptId = UserId, OptName = UserName }); } else { dbModel.Vol = vol; dbModel.OptId = UserId; dbModel.OptName = UserName; dbModel.OptDate = OptDate; } DbContext.SaveChanges(); } /// /// /// public Dictionary GetVols(DateTime date, IEnumerable tradeList) { var result = new Dictionary(); var codes = tradeList.Select(O => O.UnderlyingCode).ToHashSet(StringComparer.OrdinalIgnoreCase); var varietyMap = DbContext.underlying_manager .Where(underlyingDb => codes.Contains(underlyingDb.UnderlyingCode)) .ToDictionary(K => K.UnderlyingCode, V => V.UnderlyingTypeId, StringComparer.OrdinalIgnoreCase); var vols = GetVols(date, varietyMap.Values); foreach (var t in tradeList) { if (varietyMap.TryGetValue(t.UnderlyingCode, out var vid)) { result[t.id] = vols.Find(O => O.VarietyId == vid).Vol; } else { throw new Exception($"标的'{t.UnderlyingCode}'找不到光证波动率,因未关联品种"); } } return result; } /// /// /// public static double? GetVarietyVol(DateTime valueDate, int varietyId) { using (var db = DbContextFactory.GetYLDbContext()) { var query = from v in db.variety_vol where v.VarietyId == varietyId && v.ValueDate <= valueDate orderby v.ValueDate descending select (double?)v.Vol; return query.FirstOrDefault(); } } /// /// /// public static double? GetVarietyVol(DateTime valueDate, string underlyingCode) { if (string.IsNullOrWhiteSpace(underlyingCode)) { return null; } using (var db = DbContextFactory.GetYLDbContext()) { var query = from un in db.underlying_manager.Where(n => n.UnderlyingCode == underlyingCode) join v in db.variety_vol on un.UnderlyingTypeId equals v.VarietyId where v.ValueDate <= valueDate orderby v.ValueDate descending select (double?)v.Vol; return query.FirstOrDefault(); } } } }