using Newtonsoft.Json; using System.Data; using YLErp.BLL.Calculation; using YLErp.Commons; using YLErp.DBModels.Consts; using YLErp.Modules.TQuoteModule; using YLErp.Modules.VolatilityModule; using YLErp.QdpModule; using YLErp.QdpModule.Constants; namespace YLErp.Web.Controllers { public class volatilityController : BaseController { /// /// todo 保存多个类型的voltity /// public JsonResult SubmitSurface2(List vols) { if (!CurUser.报价管理_波动率曲面修改) { return JsonError("没有保存权限"); } var userVarietyIds = CurUser.GetUserVarietyIds().ToHashSet(); var unIdSet = vols.Select(n => n.UnderlyingId ?? 0).ToHashSet(); var unAuthCodes = DataCacheProvider.GetUnderlyingDataSource().AsQueryable() .Where(n => unIdSet.Contains(n.id) && !userVarietyIds.Contains(n.UnderlyingTypeId)) .Select(n => n.UnderlyingCode).ToArray(); if (unAuthCodes.Any()) { return JsonError("更新曲面失败,没有品种交易权限:" + string.Join(",", unAuthCodes)); } try { foreach (var vv in vols) { vv.QuotationDate = valuedateBLL.ValueDate; vv.UserGroup = CurUser.UserGroup; vv.OptId = UserId; vv.OptName = UserName; } var vollist = new VolatilitySaveService(CurUser).SaveVols(vols); return JsonSuccess("更新曲面成功", vollist); } catch (Exception ex) { LogFactory.GetLogger(nameof(SubmitSurface2)).Error("更新曲面波动率", ex); return JsonError("更新曲面失败," + ex.Message); } } /// /// 计算价格 /// public JsonResult TQuote(TQuoteRequest req) { if (req.strikeInterval == 0) { return JsonError("执行价间隔不能为0!"); } return JsonSuccess("", new TQuoteService(CurUser).Execute(req)); } public JsonResult TQuoteWithCustomizedVol(TQuoteWithCustomizedVolRequest request) { return JsonSuccess("", new TQuoteService(CurUser).TQuoteWithCustomizedVol(request)); } [MyAuthorize("报价管理-T型报价查看")] public ActionResult t_table() { return View(); } [MyAuthorize("报价管理-波动率曲面查看")] public ActionResult today_volsurface_edit(int? uid, string voltype) { if (PS.Config.ErpElement.SkewMapVolConstruction && uid == null && voltype == null) { return RedirectToAction("index", "skewMap"); } if (ConsUserGroup.HasGroup && string.IsNullOrEmpty(CurUser.UserGroup)) { return ShowError("当前用户必须设置用户组以后才能访问此页面"); } return today_volsurface_editV2(); } [MyAuthorize("报价管理-波动率曲面查看")] public ActionResult today_volsurface_editV2() { if (PS.Config.ErpElement.SkewMapVolConstruction) { return RedirectToAction("index", "skewMap"); } if (ConsUserGroup.HasGroup && string.IsNullOrEmpty(CurUser.UserGroup)) { return ShowError("当前用户必须设置用户组以后才能访问此页面"); } var model = new VolsurfaceEditModel(CurUser); return View("today_volsurface_editV2", model); } [MyAuthorize("报价管理-波动率曲面查看")] public ActionResult riskFreeCurve() { return View(); } public JsonResult get_underlyingvolsurface(string ucode, string voltype, DateTime systemdate) { var underlying = underlying_managerBLL.GetByCode(ucode); //加入t型表格行权日时间 var tTableExecerizeDate = DateTime.Now.AddMonths(1).AddDays(-1); if (underlying.MaturityDate < tTableExecerizeDate) { tTableExecerizeDate = underlying.MaturityDate.Value; } underlying.ExerciseDate = QdpCalendarHelper.GetNonHoliday(tTableExecerizeDate); var request = new SingleVolatilityRequest { QuotationDate = systemdate, UnderlyingCode = ucode, TradeVolWithBidAsk = true, UserGroup = CurUser.UserGroup, VolType = voltype }; var all_volatilities = new VolatilityQueryService(CurUser).GetVolatility(request, true); var VolTypes = request.GetVolTypes().Select(O => new VolTypeState() { VolModelName = O }).ToList(); return JsonSuccess("获取波动率曲面成功", new { underlying, all_volatilities, VolTypes }); } public ActionResult volsurfaceUpload() { var voldate = valuedateBLL.ValueDate; ViewBag.Voldate = voldate.ToString("yyyy-MM-dd"); var r = new volatility(); return View(r); } public ActionResult UploadVolSurface(IFormFile file) { try { double.TryParse(Request.Form["Ask_Deviation"], out var ask_deviation); double.TryParse(Request.Form["Bid_Deviation"], out var bid_deviation); var quotationDate = Convert.ToDateTime(HttpContext.Request.Form["QuotationDate"]); var overridByMainCode = "true".Equals(Request.Form["overridByMainCode"], StringComparison.OrdinalIgnoreCase); using var stream = file.OpenReadStream(); var volList = new VolatilityImportReadService(CurUser).ImportFile(stream, new VolatilityImportReadModel { quotationDate = quotationDate, Ask_Deviation = ask_deviation, Bid_Deviation = bid_deviation, volType = Request.Form["VolType"], volSurfaceMode = Request.Form["VolSurfaceMode"], ReviewDownLimit = ConsVolInfos.defReviewDownLimit, ReviewUpLimit = ConsVolInfos.defReviewUpLimit, UserGroup = CurUser.UserGroup }); //保存更新波动率信息 if (volList.Count > 0) { var saveVols = new VolatilitySaveService(CurUser).SaveVols(volList, overridByMainCode); if (saveVols.Count == 0) { return JsonError("导入失败,请检查交易和BidAsk的行权价及到期日是否一致,且波动率是否为正数"); } } else { return JsonError("没有导入波动率"); } return JsonSuccessData(new { version = "v2", vol = volList.First(), underlyingCode = volList.First().ContractCode }); } catch (Exception ex) { LogFactory.GetLogger().Error("UploadFiles", ex); return JsonError(ex.Message); } } public ActionResult volsurfaceDown() { ViewBag.valueDate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd"); volatility r = null; return View(r); } [HttpPost] public ActionResult downLoadVolSurfaceList(BatchVolatilityRequest req) { //获取角色有权限的 var varietyIds = CurUser.GetUserVarietyIds(); if (!varietyIds.Any(n => n > 0)) { return ShowError("当前账户没有标的查看权限!"); } req.VarietyIds = varietyIds; req.UserGroup = CurUser.UserGroup; //根据条件获取波动率数据 var volList = new VolatilityQueryService(CurUser).GetVolatilities(req, false); if (volList == null || !volList.Any()) { return ShowError("当前条件下未查找到波动率曲面数据!导出失败!"); } var dt = VolatilityHelper.GetMatrix(volList); var helper = new ExcelHelper(); var volType = ""; switch (req.VolType) { case "交易": volType = "Mid"; break; case "报价Bid": volType = "Bid"; break; case "报价Ask": volType = "Ask"; break; default: volType = req.VolType; break; } if (helper.DataTableToExcel(dt, volType, false, out var buffer) < 0) { return ShowError("导出失败!"); } return File(buffer, "application/ms-excel", $"波动率曲面-{req.QuotationDate:yyyy-MM-dd}.xlsx"); } /// /// 获取某一标的的历史波动率曲线 /// /// 合约代码 /// 日期 /// 计算波动率回溯的天数,可为30、60、90 /// public JsonResult GetHistoricalVolCurve(string underlyingCode, DateTime valueDate, int lookBackDays) { var volPoints = VolCaculator.Instance.GetHistoricalVolCurvePoints(underlyingCode, valueDate, lookBackDays); return Json(volPoints); } /// /// 在用户设置的原始波动率曲面的点之间通过插值计算出更密集的点,以方便画出更准确的曲面图 /// /// 原始波动率曲面 /// 插值方法 /// public JsonResult FillVolSurfaceInterpolatePoints(VolSurfacePoints[] volSurfaces, string interpolation) { var result = new Dictionary(); foreach (var vol in volSurfaces) { result[vol.SurfaceName] = VolCaculator.Instance.FillInterpolatePoints(vol.Points, interpolation); } return Json(result); } /// /// 根据用户选择的期限,获得相应的波动率曲线的点,这些点除了包括原始的点之外,还包括通过插值计算出更密集的点 /// /// 原始波动率曲面 /// 插值方法 /// 期限 /// public JsonResult Fill2DVolSmileCurvePoints(VolSurfacePoints[] volSurfaces, string interpolation, string expire) { var result = new Dictionary(); foreach (var vol in volSurfaces) { result[vol.SurfaceName] = VolCaculator.Instance.FillVolSmileCurvePoints(vol.Points, interpolation, expire); } return Json(result); } /// /// 获取某一标的的隐含波动率曲面。只对有场内期权的标的有效 /// /// /// /// public JsonResult GetImpliedVolSurface(string underlyingCode, DateTime valueDate) { var underlying = underlying_managerBLL.GetByCode(underlyingCode); //加入t型表格行权日时间 var tTableExecerizeDate = DateTime.Now.AddMonths(1).AddDays(-1); if (underlying.MaturityDate < tTableExecerizeDate) { tTableExecerizeDate = underlying.MaturityDate.Value; } underlying.ExerciseDate = QdpCalendarHelper.GetNonHoliday(tTableExecerizeDate); var VolTypes = ConsVolInfos.GetVolTypes("隐含") .Select(O => new VolTypeState() { VolModelName = O }).ToList(); var volTypeList = VolTypes.Select(v => v.VolModelName).ToList(); var volatility = VolCaculator.Instance.GetImpliedVolSurface(underlyingCode, valueDate); if (volatility == null) { return JsonError("获取隐含波动率失败。请确认该标的有场内期权且系统中有场内期权价格数据"); } var all_volatilities = new List { volatility }; return JsonSuccess("获取波动率曲面成功", new { underlying, VolTypes, all_volatilities }); } public JsonResult GetRiskFreeCurve() { var curvePointData = valuedateBLL.RiskFreeCurveData; if (string.IsNullOrWhiteSpace(curvePointData)) { return JsonError("未查询到系统里有已设置的利率曲线,请重新设置"); } var curvePoints = JsonConvert.DeserializeObject>(curvePointData); return JsonSuccess("", curvePoints); } [HttpPost] public ActionResult SaveRiskFreeCurve(List curvePoints) { var config = yldb.valuedate.FirstOrDefault(v => v.State == valuedate.当前使用); config.RiskFreeCurveData = (curvePoints != null && curvePoints.Count > 0) ? JsonConvert.SerializeObject(curvePoints.Where(p => !double.IsNaN(p.Rate)).ToList()) : ""; config.UpdateTime = DateTime.Now; yldb.SaveChanges(); valuedateBLL.ResetValueDate(); return JsonSuccess("曲线保存成功"); } } }