using Qdp.Pricing.Base.Implementations; using Qdp.Pricing.Library.Equity.Engines.Analytical; namespace YLErp.Modules.VolatilityModule { /// /// 交易波动率提供(适用于UseTradeVol) /// public class TradeVolitalityProvider { protected readonly DateTime _valueDate; Dictionary _dicData; public TradeVolitalityProvider(DateTime valueDate) { _valueDate = valueDate.Date; } /// /// 如果设为true程序内部将不会再进行数据初始化, /// 这样做的目的是为了少量数据获取时避免初始化带来的性能损失 /// public bool Initialized { get; set; } private void Initialize() { if (_dicData != null) { return; } lock (this) { if (_dicData != null) { return; } if (Initialized) { _dicData = new Dictionary(); } else { //只取3个月以内的 var startDate = _valueDate.AddMonths(-3); using var db = DbContextFactory.GetYLDbContext(); var query1 = from a in db.TradeVolatility where a.ValueDate > startDate && a.ValueDate <= _valueDate group a by a.TradeId into g select new { TradeId = g.Key, ValueDate = g.Max(n => n.ValueDate) }; var query2 = from a in query1 join b in db.TradeVolatility on a equals new { b.TradeId, b.ValueDate } select new InnerTradeVolatility { TradeId = b.TradeId, ValueDate = b.ValueDate, NumOfSmoothingDays = b.NumOfSmoothingDays, TradePositionVolatility = b.TradePositionVolatility, TradeCloseVolatility = b.TradeCloseVolatility, IsFromTradeAdd = b.IsFromTradeAdd }; _dicData = query2.ToDictionary(n => n.TradeId, m => m); } } } public bool TryGetVol(int tradeId, DateTime tradeExerciseDate, out double vol) { Initialize(); if (!_dicData.TryGetValue(tradeId, out var tradeVol) && tradeId > 0) { using var db = DbContextFactory.GetYLDbContext(); _dicData[tradeId] = tradeVol = db.TradeVolatility .Where(v => v.TradeId == tradeId && v.ValueDate <= _valueDate) .OrderByDescending(v => v.ValueDate) .Select(b => new InnerTradeVolatility { TradeId = b.TradeId, ValueDate = b.ValueDate, NumOfSmoothingDays = b.NumOfSmoothingDays, TradePositionVolatility = b.TradePositionVolatility, TradeCloseVolatility = b.TradeCloseVolatility, IsFromTradeAdd = b.IsFromTradeAdd }).FirstOrDefault(); } if (tradeVol == null) { vol = 0; return false; } if (tradeVol.ResultVol.HasValue) { vol = tradeVol.ResultVol.Value; return true; } if (_valueDate < tradeVol.ValueDate) { vol = tradeVol.TradePositionVolatility ?? 0; } else if (_valueDate > tradeExerciseDate) { vol = tradeVol.TradeCloseVolatility ?? 0; } else { var daycountMode = PS.Config.ErpElement.SmoothingDaycountMode == Configuration.Enums.SmoothingDaycountMode.CalendarDay ? Qdp.Pricing.Base.Enums.DayCountMode.CalendarDay : Qdp.Pricing.Base.Enums.DayCountMode.TradingDay; //新增交易当天的持仓波动率需要划掉一天,修改后的持仓波动率不需要再划一天 vol = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp( new Qdp.Foundation.Implementations.Date(_valueDate), tradeVol.TradePositionVolatility ?? 0, tradeVol.TradeCloseVolatility ?? 0, new Qdp.Foundation.Implementations.Date(tradeVol.ValueDate), new Qdp.Foundation.Implementations.Date(tradeExerciseDate), tradeVol.NumOfSmoothingDays ?? 0, daycountMode, CalendarImpl.Get("chn"), includeStartDate: tradeVol.IsFromTradeAdd); } tradeVol.ResultVol = vol; return true; } class InnerTradeVolatility { public int TradeId { get; set; } /// /// 操作系统日 /// public DateTime ValueDate { get; set; } /// /// 持仓波动率 /// public double? TradePositionVolatility { get; set; } /// /// 目标波动率 /// public double? TradeCloseVolatility { get; set; } /// /// 平滑天数 /// public int? NumOfSmoothingDays { get; set; } /// /// 是否是新增交易时添加的波动率记录 /// public bool IsFromTradeAdd { get; set; } public double? ResultVol { get; set; } } } }