using YLErp.BLL; using YLErp.Model; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule.DealModule { /// /// 价差期权数据验证 /// public static class SpreadOptionValidator { /// /// 验证价差期权数据 /// public static string Validate(trade req) { var errorMsg = ""; SpreadOptionPayoff payoff = null; try { payoff = new SpreadOptionPayoff(req.trade_spread_option.Payoff); } catch (ArgumentException e) { errorMsg = e.Message; } var numberOfUnderlyings = payoff.Weights.Length; if (string.IsNullOrEmpty(errorMsg)) { req.trade_spread_option.UnderlyingId1 = req.UnderlyingId; req.trade_spread_option.UnderlyingAssetCode1 = req.UnderlyingCode; req.trade_spread_option.TradeOpenVolatility1 = req.TradeOpenVolatility; req.trade_spread_option.TradeCloseVolatility1 = req.TradeCloseVolatility; req.trade_spread_option.NumOfSmoothingDays1 = req.NumOfSmoothingDays; // remove redundant underlying ids/codes if (numberOfUnderlyings == 2) { req.trade_spread_option.UnderlyingId3 = null; req.trade_spread_option.UnderlyingId4 = null; req.trade_spread_option.UnderlyingAssetCode3 = null; req.trade_spread_option.UnderlyingAssetCode4 = null; } else if (numberOfUnderlyings == 3) { req.trade_spread_option.UnderlyingId4 = null; req.trade_spread_option.UnderlyingAssetCode4 = null; } if (!req.trade_spread_option.UnderlyingId1.HasValue || string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode1) || !req.trade_spread_option.UnderlyingId2.HasValue || string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode2)) { errorMsg = "标的ID和代码不能为空"; } if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 3) { if (!req.trade_spread_option.UnderlyingId3.HasValue || string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode3)) { errorMsg = "标的ID和代码不能为空"; } if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 4) { if (!req.trade_spread_option.UnderlyingId4.HasValue || string.IsNullOrEmpty(req.trade_spread_option.UnderlyingAssetCode4)) { errorMsg = "标的ID和代码不能为空"; } } } } if (string.IsNullOrEmpty(errorMsg)) { errorMsg = checkSpreadOptionVolatilitySettings(req, numberOfUnderlyings); } if (string.IsNullOrEmpty(errorMsg)) { errorMsg = checkCorrelations(req.trade_spread_option); } return errorMsg; } private static string checkCorrelations(trade_spread_option spreadOption) { var errorMsg = ""; var ids = spreadOption.UnderlyingIds(); var codes = spreadOption.UnderlyingAssetCodes(); using (var db = DbContextFactory.GetYLDbContext()) { for (int i = 0; i < ids.Length - 1 && string.IsNullOrEmpty(errorMsg); i++) { for (int j = i + 1; j < ids.Length && string.IsNullOrEmpty(errorMsg); j++) { if (correlationBLL.findCorrelation(ids[i], ids[j], db) == 0.0) { errorMsg = $"未设定{codes[i]}与{codes[j]}的相关性"; } } } } return errorMsg; } private static string checkSpreadOptionVolatilitySettings(trade req, int numberOfUnderlyings) { var errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility2, req.trade_spread_option.TradeCloseVolatility2, req.trade_spread_option.NumOfSmoothingDays2, req.StartDate, req.ExerciseDate); if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 3) { errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility3, req.trade_spread_option.TradeCloseVolatility3, req.trade_spread_option.NumOfSmoothingDays3, req.StartDate, req.ExerciseDate); } if (string.IsNullOrEmpty(errorMsg) && numberOfUnderlyings >= 4) { errorMsg = checkVolatilitySetting(req.trade_spread_option.TradeOpenVolatility4, req.trade_spread_option.TradeCloseVolatility4, req.trade_spread_option.NumOfSmoothingDays4, req.StartDate, req.ExerciseDate); } return errorMsg; } private static string checkVolatilitySetting(double? open, double? close, int? smoothing, DateTime? startDate, DateTime? exerciseDate) { if (open.HasValue && open.Value < 0) { return "开仓波动率不能小于0"; } if (close.HasValue && close.Value < 0) { return "目标波动率不能小于0"; } if (smoothing.HasValue) { if (smoothing.Value < 0) { return "平滑过渡天数不能小于0"; } if (exerciseDate.HasValue && startDate.HasValue && smoothing > QdpCalendarHelper.GetNonHolidayDaysBetween(startDate.Value, exerciseDate.Value) + 1) { return "平滑过渡天数不能大于存续天数"; } } return ""; } } }