using Newtonsoft.Json; using System.Data; using YLErp.BLL; namespace YLErp.Modules.UnderlyingModule { /// /// 篮子标的信息管理服务 /// public class BasketUnderlyingService : YLBaseService { public BasketUnderlyingService(YLBaseService baseService) : base(baseService) { } public BasketUnderlyingService(OptUserInfo userInfo) : base(userInfo) { } /// /// 组合标的导入xlsx数据 /// public BasketUnderlyingDto ImportBasketDatasFromExcel(Stream stream) { var result = new BasketUnderlyingDto(); try { //当前编码支持ansi和utf with bom var ds = Office.ExcelHelper.ReadExcelAsDataSet(stream); if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 1) { throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" }; } var table = ds.Tables[0]; List list = new List(); if (table.Rows.Count < 1) { throw new ServiceException("导入数据不能为空!"); } var useWhiteCode = new StockBlackWhiteService(UserInfo).GetStockBlackWhiteList(Configuration.Enums.LimitRangeEnum.Swap, out var Codes); foreach (DataRow row in table.Rows) { if (row.IsNull("标的代码") || row.IsNull("标的权重")) { throw new ServiceException("导入标的代码或标的权重不能为空!"); } double price = 0; BasketUnderlyingItem importModel = new BasketUnderlyingItem(); importModel.code = (string)row["标的代码"]; double.TryParse((row["标的权重"]?.ToString() ?? ""), out var weight); importModel.weight = weight; double.TryParse((row["标的份额"]?.ToString() ?? ""), out var notional); importModel.notional = notional; DataCacheProvider.GetUnderlyingDataSource().TryGetPrice(importModel.code, out price); var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(importModel.code); if (underlying == null) { throw new ServiceException("标的代码不存在: " + importModel.code); } if (ConsGlobal.InstrumentType.IsStock(underlying.UnderlyingInstrumentType) && Codes != null && useWhiteCode == Codes.Contains(importModel.code)) { throw new ServiceException($"标的代码:{importModel.code} {(useWhiteCode ? "存在于黑名单中" : "不在白名单中")}"); } importModel.Price = price; list.Add(importModel); } result.Items = list; } catch (Exception ex) { throw (ex.InnerException as ServiceException) ?? ex; } if (!result.Items.Any()) { throw new ServiceException("没有可导入的数据"); } return result; } /// /// 保存篮子标的数据 /// public int SaveBasketUnderlying(BasketUnderlyingDto model) { if (model is null) { throw new ArgumentNullException(nameof(model)); } if (string.IsNullOrWhiteSpace(model.UnderlyingCode)) { throw new ServiceException("别名不能为空"); } if (DbContext.underlying_manager.Any(n => n.UnderlyingCode == model.UnderlyingCode)) { throw new ServiceException("系统中已有重名的组合标的"); } if (model.Items == null || !model.Items.Any()) { throw new ServiceException("篮子标的列表没有任何数据"); } if (model.Items.Any(n => string.IsNullOrWhiteSpace(n.code))) { throw new ServiceException("篮子标的列表中不应存在空白标的"); } var isAddNew = model.id <= 0; //---------------------------------- // 存入underlying_manager表 //---------------------------------- var variety = UnderlyingHelper.GetBasketVariety(); //---------------------------------- // 2020/5/14 获取组合标的的第一个标的 //---------------------------------- var underlyingCode1 = model.Items.First().code; var underlying1 = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode1); if (underlying1 == null) { throw new ServiceException("标的数据未找到:" + underlyingCode1); } // 篮子标的到期日 DateTime? MaturityDate = DateTime.MaxValue; foreach (var item in model.Items) { DateTime? Date = DataCacheProvider.GetUnderlyingDataSource().GetData(item.code).MaturityDate; MaturityDate = Date < MaturityDate ? Date : MaturityDate; item.Price = null; } //---------------------------------- // 新增variety 如果没有该品种 则新增 //------------- if (variety.id == 0) { variety = new Variety() { VarietyCode = "篮子标的", VarietyName = "篮子标的", OptId = model.OptId, OptName = model.OptName, OptDate = model.OptDate, TradingMarketId = 0, TradeUnit = "100股/手", QuoteUnit = "元(人民币)/股", DeliveryType = "", HasNightMarket = false, ShortName = "篮子标的", CommissionType = "固定", CloseTodayCommissionType = "固定", //UnderlyingInstrumentType = "Stock", VolatilityRate = "", VolatilityAdjust = 0 }; DbContext.variety.Add(variety); DbContext.SaveChanges(); } underlying_manager underlying; if (isAddNew) { underlying = new underlying_manager { UnderlyingCode = model.UnderlyingCode, UnderlyingType = variety.VarietyName, UnderlyingTypeId = variety.id, UnderlyingName = model.UnderlyingCode, CommodityCode = variety.VarietyCode, OpenDate = DateTime.Today }; DbContext.underlying_manager.Add(underlying); } else { underlying = DbContext.underlying_manager.FirstOrDefault(u => u.UnderlyingCode == model.UnderlyingCode); if (underlying == null) { throw new ServiceException("数据不存在:" + model.UnderlyingCode); } underlying.LaunchState = "1"; underlying.LastUpdateTime = OptDate; } underlying.SubData = JsonHelper.Stringify(model.Items); underlying.OptId = UserId; underlying.OptName = UserName; underlying.OptDate = OptDate; underlying.Price = 0; underlying.MaturityDate = MaturityDate == DateTime.MaxValue ? null : MaturityDate; underlying.UnderlyingState = "Live"; underlying.UnderlyingStatus = "正常运行"; underlying.MarketCode = underlying1.MarketCode; underlying.UnderlyingInstrumentType = underlying1.UnderlyingInstrumentType; //---------------------------------- //2020/5/14 使用组合标的的第一个标的为新添加的字段赋值 //---------------------------------- underlying.TradeUnit = underlying1.TradeUnit; underlying.QuoteUnit = underlying1.QuoteUnit; underlying.MarketName = underlying1.MarketName; if (string.IsNullOrEmpty(underlying.TradeUnit)) { underlying.TradeUnit = "份"; } DbContext.SaveChanges(); //---------------------------------- // 新增underlying_parameter //---------------------------------- var underlyingParams = DbContext.underlying_parameter.Where(u => u.UnderlyingId == underlying.id).ToList(); //如果没有报价参数,则新增 if (underlyingParams.Count == 0) { underlying_parameter.defaultQuoteTypes.ForEach(t => { var up = new underlying_parameter() { NoRiskRate = valuedateBLL.SystemDate.RiskFreeRate * 0.01, Price = 0, Gamma = 0, Rho = 0, Vega = 0, Theta = 0, Delta = 0, UnderlyingId = underlying.id, Type = t, OptDate = DateTime.Now, OptId = model.OptId, OptName = model.OptName }; DbContext.underlying_parameter.Add(up); underlyingParams.Add(up); }); } //最后调用保存以保证事物完整性 return DbContext.SaveChanges(); } /// /// 篮子标的查看 /// public BasketUnderlyingDto GetBasketUnderlyingByName(string name) { var query = from u in DbContext.underlying_manager.AsEnumerable() where u.UnderlyingCode == name select new BasketUnderlyingDto { Items = JsonConvert.DeserializeObject>(u.SubData), }; var res = query.FirstOrDefault(); double price = 0; foreach (var item in res.Items) { DataCacheProvider.GetUnderlyingDataSource().TryGetPrice(item.code, out price); item.Price = price; } return res; } } /// /// /// public class BasketUnderlyingDto : UnderlyingManagerDto { /// /// 篮子标的项目 /// public IEnumerable Items { get; set; } } /// /// 篮子标的合成项 /// public class BasketUnderlyingItem { public double? Price { get; set; } /// /// 权重 /// public double weight { get; set; } /// /// 份额 /// public double notional { get; set; } /// /// 标的代码 /// public string code { get; set; } } }