using System.Data; using System.Text; using System.Text.RegularExpressions; using YLErp.Commons; using YLErp.Modules.SkewMapVolModule; using YLErp.Modules.VolatilityModule; using YLErp.QdpModule; using YLErp.QdpModule.Constants; namespace YLErp.Web.Controllers { [MyAuthorizeIgnore] public class skewMapController : BaseController { public ActionResult Index() { return View(new BasicViewModel(CurUser)); } public ActionResult GetBaseVol(string underlyingCode, DateTime valueDate) { if (QdpCalendarHelper.IsHoliday(valueDate)) { return JsonSuccess(); } var vol = VolatilityHelper.GetVol(valueDate, "交易", underlyingCode, null); return JsonSuccessData(vol); } public ActionResult SetBaseVol(volatility vol) { if (vol is null) { throw new ArgumentNullException(nameof(vol)); } var un = yldb.underlying_manager.Where(n => n.UnderlyingCode == vol.ContractCode) .Select(n => new { n.id }).FirstOrDefault(); if (un == null) { return JsonError("标的信息不存在:" + vol.ContractCode); } vol.UnderlyingId = un.id; vol.VolType = "交易"; vol.VolSurfaceMode = "MoneynessVol"; vol.InterpolationMethod = ConsVolMethod.BiLinear; vol.OptDate = DateTime.Now; var cur_vol = new VolatilitySaveService(CurUser).SaveVol(vol); return JsonSuccessData(cur_vol.First()); } /// /// 上传SkewMap文件CSV /// public ActionResult UploadSkewMap(string skewMapType) { if (string.IsNullOrEmpty(skewMapType)) { return Json(Return.Fail("skewMapType 不应为空")); } var files = Request.Form.Files; if (files == null || files.Count == 0) { return Json(Return.Fail("上传文件不存在")); } if (files[0].Length < 1) { return Json(Return.Fail("上传文件内容为空")); } try { using var stream = files[0].OpenReadStream(); using (var ms = new MemoryStream()) { stream.CopyTo(ms); var content = Encoding.UTF8.GetString(ms.ToArray()); var result = VolSkewMapInitializerSingleton.Instance.SetSkewMapData(content, skewMapType.ToLower() == "bid"); return result ? JsonSuccess("成功") : JsonError("失败"); } } catch (Exception ex) { return JsonError("保存失败," + ex.Messages()); } } /// /// 下载SkewMap文件CSV /// public ActionResult DownLoadSkewMap(string type) { try { using (var db = new YLContext()) { var queryObj = db.globalSkewMap.FirstOrDefault(O => O.SkewMapType == type); if (queryObj == null) { return ShowError("文件不存在"); } var buffer = Encoding.UTF8.GetBytes(queryObj.SkewMapTableData); return File(buffer, "application/ms-excel", $"SkewMap-{type}.csv"); } } catch (Exception e) { return ShowError("下载失败," + e.Messages()); } } /// /// 上传BaseVol文件Excel /// public ActionResult UploadBaseVol() { var files = Request.Form.Files; if (files == null || files.Count == 0) { return Json(Return.Fail("上传文件不存在")); } var helper = new ExcelHelper(); using var stream = files[0].OpenReadStream(); var dt = helper.ExcelToDataTable(stream, "Sheet1", false); if (dt.Columns.Count != 2) { return Json(Return.Fail("数据格式有误")); } var StrikeRow = 0; var volatilitys = new List(); var unProvider = Modules.DataCacheProvider.GetUnderlyingDataSource(); volatility volObj = null; List singleVols = null; for (var i = 0; i < dt.Rows.Count; i++) { var drow = dt.Rows[i]; if (string.IsNullOrWhiteSpace(drow[0]?.ToString())) { volObj.Data = singleVols.ToJson(); StrikeRow = i + 1; continue; } if (StrikeRow == i) { var code = drow[0]?.ToString(); var strike = double.Parse(dt.Rows[StrikeRow][1].ToString()); if (OtcFormatHelper.FormatValue(strike, 2) != 1) { return Json(Return.Fail($"{code}的 Strike 不为 1")); } var info = unProvider.GetData(code); if (info == null) { return JsonError("标的信息不存在:" + code); } if (info.IsFutures() && info.MaturityDate < valuedateBLL.ValueDate) { return JsonError("标的已过期:" + code); } volObj = new volatility { ContractCode = drow[0]?.ToString(), UnderlyingId = info?.id, QuotationDate = valuedateBLL.ValueDate, VolType = "交易", VolSurfaceMode = "MoneynessVol", InterpolationMethod = ConsVolMethod.BiLinear, OptDate = DateTime.Now }; if (!volatilitys.Exists(O => O.ContractCode == code))//如果存在重复代码则以第一条为准 { volatilitys.Add(volObj); } singleVols = new List(); continue; } singleVols.Add(new SingleVol() { Expire = drow[0]?.ToString(), Strike = double.Parse(dt.Rows[StrikeRow][1].ToString()), Vol = double.Parse(drow[1].ToString()) }); } if (volObj != null && volatilitys[volatilitys.Count - 1].Data == null) { volObj.Data = singleVols.ToJson(); } new VolatilitySaveService(CurUser).SaveVols(volatilitys); return JsonSuccess(); } /// /// 下载BaseVol文件Excel /// public ActionResult DownLoadBaseVol(DateTime valueDate, string underlyingCode, bool query = false) { byte[] buffer = null; try { var list = new VolatilityQueryService(CurUser).GetVolatilities(new BatchVolatilityRequest { QuotationDate = valueDate, UnderlyingCodes = string.IsNullOrEmpty(underlyingCode) ? null : new[] { underlyingCode }, TradeVolWithBidAsk = true, UserGroup = CurUser.UserGroup, VolType = "交易" }, false); if (list == null || !list.Any()) { return Json(Return.Fail("数据不存在")); } if (query)//如果只是查询数据是否存在,则只返回错误信息或数量; { return JsonSuccessData(list.Count()); } list = list.OrderBy(O => O.ContractCode).ToList(); var dt = new DataTable(); var StrikeRow = 0; dt.Columns.Add(); dt.Columns.Add(); foreach (var item in list) { dt.Rows.Add(); dt.Rows[StrikeRow][0] = item.ContractCode; var vos = item.VolTable; vos.Sort((X, Y) => { if (X == null) { return -1; } if (Y == null) { return 1; } return ExpireToDay(X.Expire) - ExpireToDay(Y.Expire); }); for (var j = 0; j < vos.Count; j++) { dt.Rows.Add(); dt.Rows[StrikeRow][1] = vos[j].Strike; dt.Rows[StrikeRow + j + 1][0] = vos[j].Expire; dt.Rows[StrikeRow + j + 1][1] = vos[j].Vol; } dt.Rows.Add(); StrikeRow = StrikeRow + vos.Count + 2; } new ExcelHelper().DataTableToExcel(dt, "Sheet1", false, out buffer); if (string.IsNullOrWhiteSpace(underlyingCode)) { underlyingCode = "All"; } return File(buffer, "application/ms-excel", $"BaseVol-{valueDate:yyyy-MM-dd}-{underlyingCode}.xlsx"); } catch (Exception e) { return ShowError("下载失败" + e.Message); } } private int ExpireToDay(string expire) { var result = 0; var m = Regex.Match(expire.ToUpper(), @"^(?\d+)(?[D|W|M|Y])$"); if (!m.Success) { return 999; } var num = int.Parse(m.Groups["num"].Value); var unit = m.Groups["unit"].Value; switch (unit) { case "D": result = int.Parse(m.Groups["num"].Value); break; case "W": result = int.Parse(m.Groups["num"].Value) * 7; break; case "M": result = int.Parse(m.Groups["num"].Value) * 30; break; case "Y": result = int.Parse(m.Groups["num"].Value) * 365; break; } return result; } public ActionResult GetVarietyVol(int varietyId, DateTime valueDate) { var data = new VarietyVolService(CurUser).GetVol(varietyId, valueDate); return JsonSuccessData(data); } public ActionResult SetVarietyVol(int varietyId, DateTime valueDate, double vol) { new VarietyVolService(CurUser).SaveData(varietyId, valueDate, vol); return JsonSuccess(); } } }