private bool TryProcessSeries(IOptionSeries optSer, DateTime now, out double ivAtm) { ivAtm = Constants.NaN; if (optSer == null) { return(false); } Dictionary <DateTime, double> ivSigmas; #region Get cache DateTime expiry = optSer.ExpirationDate.Date; string cashKey = IvOnF.GetCashKey(optSer.UnderlyingAsset.Symbol, expiry, m_rescaleTime, m_tRemainMode); object globalObj = Context.LoadGlobalObject(cashKey, true); ivSigmas = globalObj as Dictionary <DateTime, double>; // PROD-3970 - 'Важный' объект if (ivSigmas == null) { var container = globalObj as NotClearableContainer; if ((container != null) && (container.Content != null)) { ivSigmas = container.Content as Dictionary <DateTime, double>; } } if (ivSigmas == null) { ivSigmas = new Dictionary <DateTime, double>(); } #endregion Get cache ISecurity sec = optSer.UnderlyingAsset; int len = sec.Bars.Count; if (len <= 0) { return(false); } FinInfo baseFinInfo = optSer.UnderlyingAsset.FinInfo; if (baseFinInfo.LastPrice == null) { string msg = "[IV ATM (all series)] (baseFinInfo.LastPrice == null)"; m_context.Log(msg, MessageType.Warning, false); return(false); } double futPx = baseFinInfo.LastPrice.Value; if (futPx <= Double.Epsilon) { return(false); } NotAKnotCubicSpline spline = null; try { spline = IvOnF.PrepareExchangeSmileSpline(optSer, Double.MinValue, Double.MaxValue); } catch (ScriptException scriptEx) { m_context.Log(scriptEx.ToString(), MessageType.Error, false); return(false); } catch (Exception ex) { m_context.Log(ex.ToString(), MessageType.Error, false); return(false); } if (spline == null) { return(false); } try { double sigma; if (spline.TryGetValue(futPx, out sigma) && (!Double.IsNaN(sigma)) && (sigma > 0)) { ivAtm = sigma; DateTime lastBarDate = sec.Bars[len - 1].Date; if (m_rescaleTime) { #region Зверская ветка по замене времени DateTime expDate = optSer.ExpirationDate.Date + m_expiryTime; // 1. Надо перевести волатильность в абсолютную цену // с учетом плоского календарного времени применяемого РТС double plainTimeAsYears; { double plainTimeAsDays; TimeToExpiry.GetDt(expDate, now, TimeRemainMode.PlainCalendar, false, out plainTimeAsDays, out plainTimeAsYears); } // 2. Вычисляем 'нормальное' время double timeAsDays, timeAsYears; TimeToExpiry.GetDt(expDate, now, m_tRemainMode, false, out timeAsDays, out timeAsYears); sigma = FinMath.RescaleIvToAnotherTime(plainTimeAsYears, ivAtm, timeAsYears); if (DoubleUtil.IsPositive(sigma)) { ivAtm = sigma; // Это просто запись на диск. К успешности вычисления волы success отношения не имеет bool success = IvOnF.TryWrite(m_context, true, true, 1, cashKey, ivSigmas, lastBarDate, sigma); // Теперь надо вычислить безразмерный наклон кодом в классе SmileImitation5 bool successSkew = IvOnF.TryCalcAndWriteSkews(m_context, spline, true, true, 1, optSer.UnderlyingAsset.Symbol, expiry, futPx, lastBarDate, m_tRemainMode, plainTimeAsYears, timeAsYears); return(true); } else { // Если перемасштабировать улыбку не получается придется эту точку проигнорировать // Надо ли сделать соответствующую запись в логе??? return(false); } #endregion Зверская ветка по замене времени } else { // Это просто запись на диск. К успешности вычисления волы success отношения не имеет bool success = IvOnF.TryWrite(m_context, true, true, 1, cashKey, ivSigmas, lastBarDate, sigma); return(true); } } } catch (ScriptException scriptEx) { m_context.Log(scriptEx.ToString(), MessageType.Error, false); } catch (Exception ex) { m_context.Log(ex.ToString(), MessageType.Error, false); //throw; } return(false); }