/// <summary> /// Обработчик под тип входных данных OPTION /// </summary> public void Execute(IOption opt) { if (opt == null) { return; } DateTime now = opt.UnderlyingAsset.FinInfo.LastUpdate; DateTime today = now.Date; IOptionSeries[] series = opt.GetSeries().ToArray(); for (int j = 0; j < series.Length; j++) { IOptionSeries optSer = series[j]; if (optSer.ExpirationDate.Date < today) { continue; } try { double ivAtm; TryProcessSeries(optSer, now, out ivAtm); } catch (Exception ex) { string msg = String.Format("[{0}] {1} when processing option series: {2}", GetType().Name, ex.GetType().FullName, ex); m_context.Log(msg, MessageType.Warning, true); } } }
internal static bool TryEstimateGamma(double putQty, double callQty, IOptionSeries optSer, IOptionStrikePair pair, InteractiveSeries smile, NumericalGreekAlgo greekAlgo, double f, double dF, double timeToExpiry, double riskFreeRate, out double rawGamma) { rawGamma = Double.NaN; if (timeToExpiry < Double.Epsilon) { throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry); } double delta1, delta2; bool ok1 = OptionsBoardNumericalDelta.TryEstimateDelta(putQty, callQty, optSer, pair, smile, greekAlgo, f - dF, dF, timeToExpiry, riskFreeRate, out delta1); if (!ok1) { return(false); } bool ok2 = OptionsBoardNumericalDelta.TryEstimateDelta(putQty, callQty, optSer, pair, smile, greekAlgo, f + dF, dF, timeToExpiry, riskFreeRate, out delta2); if (!ok2) { return(false); } rawGamma = (delta2 - delta1) / 2.0 / dF; return(true); }
internal static bool TryEstimateSpeed(PositionsManager posMan, IOptionSeries optSer, IOptionStrikePair[] pairs, InteractiveSeries smile, NumericalGreekAlgo greekAlgo, double f, double dF, double timeToExpiry, out double rawSpeed) { rawSpeed = Double.NaN; if (timeToExpiry < Double.Epsilon) { throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry); } double gamma1, gamma2; bool ok1 = SingleSeriesNumericalGamma.TryEstimateGamma(posMan, optSer, pairs, smile, greekAlgo, f - dF, dF, timeToExpiry, out gamma1); if (!ok1) { return(false); } bool ok2 = SingleSeriesNumericalGamma.TryEstimateGamma(posMan, optSer, pairs, smile, greekAlgo, f + dF, dF, timeToExpiry, out gamma2); if (!ok2) { return(false); } rawSpeed = (gamma2 - gamma1) / 2.0 / dF; return(true); }
internal static bool TryEstimatePrice(double putQty, double callQty, IOptionSeries optSer, IOptionStrikePair pair, InteractiveSeries smile, double f, double timeToExpiry, double riskFreeRate, out double rawPrice) { rawPrice = Double.NaN; if (timeToExpiry < Double.Epsilon) { throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry); } double pnl1 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect1 = true; { double pairPnl; pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPrice( putQty, callQty, smile, pair, f, timeToExpiry, riskFreeRate, out pairPnl); pnl1 += pairPnl; } if (pnlIsCorrect1) { //rawPrice = (cash1 + pnl1); // В моих терминах "Цена одного опциона" будет даваться величиной pnl1 rawPrice = pnl1; return(true); } else { return(false); } }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES /// </summary> public IList <double> Execute(IOptionSeries optSer) { if (optSer == null) { // [{0}] Empty input (option series is NULL). string msg = RM.GetStringFormat("OptHandlerMsg.OptionSeriesIsNull", GetType().Name); m_context.Log(msg, MessageType.Warning, true); return(Constants.EmptyListDouble); } IList <double> res; ISecurity sec = optSer.UnderlyingAsset; switch (m_expiryMode) { case ExpiryMode.FixedExpiry: res = PrepareData(sec, Expiry); break; default: string optSerExpiry = optSer.ExpirationDate.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); res = PrepareData(sec, optSerExpiry); break; } return(res); }
/// <summary> /// Метод для передачи на вход серии опционов и также в явном виде на вход передаётся разрешение на выполнение дельта-хеджа /// </summary> public double Execute(double price, double rawDelta, IOptionSeries optSer, bool permissionToWork, int barNum) { if ((optSer == null) || (optSer.UnderlyingAsset == null)) { return(Constants.NaN); } int len = m_context.BarsCount; if (len <= 0) { return(Constants.NaN); } if (len <= barNum) { string msg = String.Format("[{0}] (BarsCount <= barNum)! BarsCount:{1}; barNum:{2}", GetType().Name, m_context.BarsCount, barNum); m_context.Log(msg, MessageType.Info, true); barNum = len - 1; } ISecurity under = optSer.UnderlyingAsset; DateTime now = under.Bars[barNum].Date; var strikes = optSer.GetStrikes(); double res = CommonExecute(m_variableId + "_rawDeltas", now, true, true, false, barNum, new object[] { price, rawDelta, under.Tick, optSer.ExpirationDate, under.Symbol, under.FinInfo.LastUpdate, under.SecurityDescription, permissionToWork, strikes, under.LotTick }); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (7 аргументов) /// </summary> public IOptionSeries Execute(IOptionSeries opt1, IOptionSeries opt2, IOptionSeries opt3, IOptionSeries opt4, IOptionSeries opt5, IOptionSeries opt6, IOptionSeries opt7) { IOptionSeries res = Select(opt1, opt2, opt3, opt4, opt5, opt6, opt7); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (8 аргументов) /// </summary> public IOptionSeries Execute(IOptionSeries opt1, IOptionSeries opt2, IOptionSeries opt3, IOptionSeries opt4, IOptionSeries opt5, IOptionSeries opt6, IOptionSeries opt7, IOptionSeries opt8) { IOptionSeries res = Select(new[] { opt1, opt2, opt3, opt4, opt5, opt6, opt7, opt8 }); return(res); }
/// <summary> /// Метод для передачи на вход серии опционов /// </summary> public double Execute(double price, double rawDelta, IOptionSeries optSer, int barNum) { // PROD-4568 - По дефолту блоку разрешено работать. // См. также обсуждение на форуме: http://forum.tslab.ru/ubb/ubbthreads.php?ubb=showflat&Number=80364#Post80364 double res = Execute(price, rawDelta, optSer, true, barNum); return(res); }
/// <summary> /// Тета будет иметь размерность 'пункты за год'. /// Обычно же опционщики любят смотреть размерность 'пункты за день'. /// Поэтому полученное сырое значение ещё надо делить на количество дней в году. /// (Эквивалентно умножению на интересующий набег времени для получения дифференциала). /// </summary> internal static bool TryEstimateTheta(double putQty, double callQty, IOptionSeries optSer, IOptionStrikePair pair, InteractiveSeries smile, NumericalGreekAlgo greekAlgo, double f, double timeToExpiry, double tStep, double riskFreeRate, out double rawTheta) { rawTheta = Double.NaN; if (timeToExpiry < Double.Epsilon) { throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry); } double t1 = (timeToExpiry - tStep > Double.Epsilon) ? (timeToExpiry - tStep) : (0.5 * timeToExpiry); double pnl1 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect1 = true; { // 2. Изменение времени // ВАЖНО: нормальный алгоритм сдвига улыбки во времени будет в платной версии "Пакета Каленковича" InteractiveSeries actualSmile = SingleSeriesProfile.GetSmileAtTime(smile, NumericalGreekAlgo.FrozenSmile, t1); { double pairPnl; pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPrice( putQty, callQty, actualSmile, pair, f, t1, riskFreeRate, out pairPnl); pnl1 += pairPnl; } } double t2 = timeToExpiry + tStep; double pnl2 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect2 = true; { // ВАЖНО: нормальный алгоритм сдвига улыбки во времени будет в платной версии "Пакета Каленковича" InteractiveSeries actualSmile = SingleSeriesProfile.GetSmileAtTime(smile, NumericalGreekAlgo.FrozenSmile, t2); { double pairPnl; pnlIsCorrect2 &= SingleSeriesProfile.TryGetPairPrice( putQty, callQty, actualSmile, pair, f, t2, riskFreeRate, out pairPnl); pnl2 += pairPnl; } } if (pnlIsCorrect1 && pnlIsCorrect2) { //rawTheta = ((cash2 + pnl2) - (cash1 + pnl1)) / (t2 - t1); rawTheta = (pnl2 - pnl1) / (t2 - t1); // Переворачиваю тету, чтобы жить в календарном времени rawTheta = -rawTheta; return(true); } else { return(false); } }
/// <summary> /// Общий метод формирования списка префиксов /// </summary> private IOptionSeries Select(params IOptionSeries[] optionSeries) { if ((optionSeries == null) || (optionSeries.Length <= 0)) { string msg = String.Format("Empty argument '{0}' is not supported. I return NULL immediately.", "optionSeries"); return(null); } HashSet <string> serList = SeriesList; serList.Clear(); IOptionSeries res = null; for (int j = 0; j < optionSeries.Length; j++) { IOptionSeries ser = optionSeries[j]; if (ser == null) { continue; } DateTime today = ser.UnderlyingAsset.FinInfo.LastUpdate.Date; if (m_aliveOnly && (ser.ExpirationDate.Date < today)) { continue; } //// TODO: как быть с инструментами типа RTS-3.15??? //string prefix = ser.UnderlyingAsset.Symbol.Substring(0, 2); string prefix = ser.UnderlyingAsset.Symbol; ////char month = s_monthLetters[ser.ExpirationDate.Month - 1]; ////string serName = prefix + month + (ser.ExpirationDate.Year % 10); //// Эмпирическое правило, что опционы недельные... //// TODO: тикет на флаг IsWeekly?.. //if (Math.Abs(ser.ExpirationDate.Day - 15) > 6) // serName = serName + "w" + (ser.ExpirationDate.Day / 7 + 1); string serName = prefix + " " + ser.ExpirationDate.ToString("MM-dd", CultureInfo.InvariantCulture); serList.Add(serName); if (serName.Equals(m_optionSeries, StringComparison.InvariantCultureIgnoreCase)) { res = ser; // НАШЛИ СЕРИЮ! УРА! } } // Если серию найти не удалось, возвращаю первый аргумент if ((res == null) && (optionSeries.Length > 0) && (optionSeries[0] != null)) { res = optionSeries[0]; string msg = String.Format("Option series not found. Base asset: '{0}'; series: '{1}'. I'll return option '{2}'.", res.UnderlyingAsset.Symbol, m_optionSeries, res.UnderlyingAsset.Symbol); m_context.Log(msg, MessageType.Info, false); } return(res); }
/// <summary> /// Метод под флаг TemplateTypes.OPTION_SERIES, чтобы подключаться к источнику-БА /// </summary> public IList <double> Execute(IOptionSeries optSer) { if (optSer == null) { return(Constants.EmptyListDouble); } return(CalculateAll(null, optSer.UnderlyingAsset)); }
public InteractiveSeries Execute(double price, InteractiveSeries line, IOptionSeries optSer, int barNum) { if (optSer == null) { return(Constants.EmptySeries); } return(Execute(price, line, optSer.UnderlyingAsset, barNum)); }
/// <summary> /// Вега будет иметь размерность 'пункты за 100% волатильности'. /// Обычно же опционщики любят смотреть размерность 'пункты за 1% волатильности'. /// Поэтому полученное сырое значение ещё надо делить на 100%. /// (Эквивалентно умножению на интересующий набег волы для получения дифференциала). /// </summary> internal static bool TryEstimateVega(double putQty, double callQty, IOptionSeries optSer, IOptionStrikePair pair, InteractiveSeries smile, NumericalGreekAlgo greekAlgo, double f, double dSigma, double timeToExpiry, double riskFreeRate, out double rawVega) { rawVega = Double.NaN; if (timeToExpiry < Double.Epsilon) { throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry); } SmileInfo sInfo = smile.GetTag <SmileInfo>(); if (sInfo == null) { return(false); } double pnl1 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect1 = true; { // Для первой точки улыбку не трогаем { double pairPnl; pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPrice( putQty, callQty, smile, pair, f, timeToExpiry, riskFreeRate, out pairPnl); pnl1 += pairPnl; } } double pnl2 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect2 = true; { //InteractiveSeries actualSmile = SingleSeriesProfile.GetRaisedSmile(smile, greekAlgo, dSigma); SmileInfo actualSmile = SingleSeriesProfile.GetRaisedSmile(sInfo, greekAlgo, dSigma); double pairPnl; pnlIsCorrect2 &= SingleSeriesProfile.TryGetPairPrice( putQty, callQty, actualSmile, pair, f, timeToExpiry, riskFreeRate, out pairPnl); pnl2 += pairPnl; } if (pnlIsCorrect1 && pnlIsCorrect2) { // Первая точка совпадает с текущей, поэтому нет деления на 2. //rawVega = ((cash2 + pnl2) - (cash1 + pnl1)) / dSigma; rawVega = (pnl2 - pnl1) / dSigma; return(true); } else { return(false); } }
/// <summary> /// Метод под флаг TemplateTypes.OPTION_SERIES, чтобы подключаться к источнику-БА /// </summary> public double Execute(IOptionSeries optSer, int barNum) { if (optSer == null) { return(Double.NaN); } return(CalculateAll(null, optSer.UnderlyingAsset, barNum)); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES /// </summary> public InteractiveSeries Execute(double price, double trueTimeToExpiry, IOptionSeries optSer, int barNum) { if (optSer == null) { return(Constants.EmptySeries); } InteractiveSeries res = Execute(price, trueTimeToExpiry, optSer, 0, barNum); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES /// </summary> public InteractiveSeries Execute(IOptionSeries optSer) { if (optSer == null) { return(Constants.EmptySeries); } InteractiveSeries res = Execute(optSer, new[] { 0.0 }); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES /// </summary> public InteractiveSeries Execute(IOptionSeries optSer, int barNum) { if (optSer == null) { return(Constants.EmptySeries); } InteractiveSeries res = Execute(optSer, 0, barNum); return(res); }
/// <summary> /// Метод под флаг TemplateTypes.OPTION_SERIES, чтобы подключаться к источнику-серии /// </summary> public IList <double> Execute(IOptionSeries optSer) { if (optSer == null) { return(Constants.EmptyListDouble); } IList <double> res = ExecuteAll(optSer.UnderlyingAsset, optSer); return(res); }
/// <summary> /// Обработчик для двух аргументов -- опционной серии и страйка /// </summary> public ISecurity Execute(IOptionSeries optSer, IList <double> actualStrikes) { if ((optSer == null) || (optSer.UnderlyingAsset == null) || (actualStrikes == null) || (actualStrikes.Count <= 0)) { return(null); } // Выбор страйка по последнему значению! double actualStrike = actualStrikes[actualStrikes.Count - 1]; IOptionStrikePair pair = GetStrikePair(optSer, m_selectionMode, actualStrike); if (pair == null) { // Данного страйка нет в списке? Тогда выход. string expiryDate = optSer.ExpirationDate.Date.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); // [{0}.Execute] There is no strike '{1}' in the option series '{2} ~ {3}'. Search mode: '{4}' string msg = RM.GetStringFormat("OptHandlerMsg.SingleOption.OptionNotFound", GetType().Name, actualStrike, optSer.UnderlyingAsset, expiryDate, m_selectionMode); if (Context.Runtime.IsAgentMode /* && (!m_ignoreCacheError) */) { throw new ScriptException(msg); // PROD-5501 - Кидаем исключение. } //bool isExpired = true; //// Поскольку в этом блоке настройки m_ignoreCacheError нет, то здесь всегда IsAgentMode == false! //if (Context.Runtime.IsAgentMode) //{ // int amount = optSer.UnderlyingAsset.Bars.Count; // DateTime today = (amount > 0) ? optSer.UnderlyingAsset.Bars[amount - 1].Date : new DateTime(); // isExpired = optSer.ExpirationDate.Date.AddDays(1) < today.Date; //} // А если в режиме лаборатории, тогда только жалуемся в Главный Лог и продолжаем. Context.Log(msg, MessageType.Warning, true /* !isExpired */); return(null); } ISecurity res; if (m_optionType == StrikeType.Put) { res = pair.Put.Security; } else if (m_optionType == StrikeType.Call) { res = pair.Call.Security; } else { throw new NotSupportedException("Не могу найти опцион вида: " + m_optionType); } return(res); }
/// <summary> /// Метод под флаг TemplateTypes.OPTION_SERIES, чтобы подключаться к источнику-БА /// </summary> public IList <double> Execute(IOptionSeries optSer) { if (optSer == null) { // [{0}] Empty input (option series is NULL). string msg = RM.GetStringFormat("OptHandlerMsg.OptionSeriesIsNull", GetType().Name); m_context.Log(msg, MessageType.Warning, true); return(Constants.EmptyListDouble); } return(Execute(optSer.UnderlyingAsset)); }
public double Execute(IOptionSeries optSer, int barNumber) { double res = Execute(optSer.UnderlyingAsset, barNumber); foreach (var strike in optSer.GetStrikes()) { double comm = Execute(strike.Security, barNumber); res += comm; } return(res); }
/// <summary> /// Метод под флаг TemplateTypes.OPTION_SERIES, чтобы подключаться к источнику-серии /// </summary> public IPosition Execute(IOptionSeries optSer, int barNum) { IPosition res = null; int len = optSer.UnderlyingAsset.Bars.Count; if (len <= 0) { return(res); } if (barNum < m_context.BarsCount - 1) { return(res); } IOptionStrikePair pair; if (!optSer.TryGetStrikePair(m_fixedStrike, out pair)) { return(res); } if (m_optionType == StrikeType.Put) { ISecurity sec = (from s in m_context.Runtime.Securities where (s.SecurityDescription.Equals(pair.Put.Security.SecurityDescription)) select s).Single(); int j = GetTodayOpeningBar(sec); string msg = String.Format("Creating virtual PUT position. j:{0}; Ticker:{1}; Qty:{2}; Px:{3}", j, sec.Symbol, m_fixedQty, m_fixedPx); m_context.Log(msg, MessageType.Info, true); res = sec.Positions.MakeVirtualPosition(j, m_fixedQty, m_fixedPx, "Open PUT"); } else if (m_optionType == StrikeType.Call) { ISecurity sec = (from s in m_context.Runtime.Securities where (s.SecurityDescription.Equals(pair.Call.Security.SecurityDescription)) select s).Single(); int j = GetTodayOpeningBar(sec); string msg = String.Format("Creating virtual CALL position. j:{0}; Ticker:{1}; Qty:{2}; Px:{3}", j, sec.Symbol, m_fixedQty, m_fixedPx); m_context.Log(msg, MessageType.Info, true); res = sec.Positions.MakeVirtualPosition(j, m_fixedQty, m_fixedPx, "Open CALL"); } else { string msg = String.Format("optionType:{0} is not yet supported.", m_optionType); m_context.Log(msg, MessageType.Warning, true); } return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (с побарным вызовом) /// </summary> public double Execute(IOptionSeries optSer, int barNum) { if ((optSer == null) || (optSer.UnderlyingAsset == null)) { return(Double.NaN); // Здесь намеренно возвращаю Double.NaN? } ISecurity sec = optSer.UnderlyingAsset; string expiry = optSer.ExpirationDate.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); string symbolKey = String.Intern(String.Join("_", sec.Symbol, expiry)); var res = ExecuteWithBarNumber(sec, symbolKey, barNum); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (с потоковой обработкой) /// </summary> public IList <double> Execute(IOptionSeries optSer) { if ((optSer == null) || (optSer.UnderlyingAsset == null)) { return(Constants.EmptyListDouble); } ISecurity sec = optSer.UnderlyingAsset; string expiry = optSer.ExpirationDate.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); string symbolKey = String.Intern(String.Join("_", sec.Symbol, expiry)); var res = ExecuteStream(sec, symbolKey); return(res); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (с побарным вызовом) /// </summary> public void Execute(IOptionSeries optSer, double indicValue, int barNum) { if ((optSer == null) || (optSer.UnderlyingAsset == null) || Double.IsNaN(indicValue) || Double.IsInfinity(indicValue)) { return; } ISecurity sec = optSer.UnderlyingAsset; string expiry = optSer.ExpirationDate.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); string symbolKey = String.Intern(String.Join("_", sec.Symbol, expiry)); ExecuteWithBarNumber(sec, symbolKey, indicValue, barNum); }
/// <summary> /// Обработчик под тип входных данных OPTION_SERIES (с потоковой обработкой) /// </summary> public void Execute(IOptionSeries optSer, IList <double> indicValues) { if ((optSer == null) || (optSer.UnderlyingAsset == null) || (indicValues == null) || (indicValues.Count <= 0)) { return; } ISecurity sec = optSer.UnderlyingAsset; string expiry = optSer.ExpirationDate.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); string symbolKey = String.Intern(String.Join("_", sec.Symbol, expiry)); ExecuteStream(sec, symbolKey, indicValues); }
/// <summary> /// Метод под флаг TemplateTypes.INTERACTIVESPLINE /// </summary> public double Execute(IOptionSeries src, IOptionSeries dest, int barNum) { if ((src == null) || (dest == null)) { return(Constants.NaN); } int barsCount = m_context.BarsCount; if (!m_context.IsLastBarUsed) { barsCount--; } if (barNum < barsCount - 1) { return(Constants.NaN); } if (src.UnderlyingAsset.FinInfo.LastPrice == null) { return(Constants.NaN); } double f = src.UnderlyingAsset.FinInfo.LastPrice.Value; IOptionStrikePair[] srcPairs = src.GetStrikePairs().ToArray(); IOptionStrikePair[] destPairs = dest.GetStrikePairs().ToArray(); double counter = 0; for (int j = 0; j < srcPairs.Length; j++) { IOptionStrikePair srcPair = srcPairs[j]; if (srcPair.Strike < f - m_widthPx) { continue; } if (srcPair.Strike < f) { } } return(counter); }
public static NotAKnotCubicSpline PrepareExchangeSmileSpline(IOptionSeries optSer, double minStrike, double maxStrike) { List <double> xs = new List <double>(); List <double> ys = new List <double>(); IOptionStrikePair[] pairs = (from pair in optSer.GetStrikePairs() //orderby pair.Strike ascending -- уже отсортировано! select pair).ToArray(); for (int j = 0; j < pairs.Length; j++) { IOptionStrikePair sInfo = pairs[j]; // Сверхдалекие страйки игнорируем if ((sInfo.Strike < minStrike) || (maxStrike < sInfo.Strike)) { continue; } if ((sInfo.PutFinInfo == null) || (sInfo.CallFinInfo == null) || (!sInfo.PutFinInfo.TheoreticalPrice.HasValue) || (!sInfo.PutFinInfo.Volatility.HasValue) || (sInfo.PutFinInfo.TheoreticalPrice.Value <= 0) || (sInfo.PutFinInfo.Volatility.Value <= 0) || (!sInfo.CallFinInfo.TheoreticalPrice.HasValue) || (!sInfo.CallFinInfo.Volatility.HasValue) || (sInfo.CallFinInfo.TheoreticalPrice.Value <= 0) || (sInfo.CallFinInfo.Volatility.Value <= 0)) { continue; } // TODO: вернуть ассерт потом //System.Diagnostics.Debug.Assert( // DoubleUtil.AreClose(sInfo.PutFinInfo.Volatility.Value, sInfo.CallFinInfo.Volatility.Value), // "Exchange volas on the same strike MUST be equal! PutVola:" + sInfo.PutFinInfo.Volatility.Value + // "; CallVola:" + sInfo.CallFinInfo.Volatility.Value); xs.Add(sInfo.Strike); ys.Add(sInfo.PutFinInfo.Volatility.Value); } NotAKnotCubicSpline spline = null; if (xs.Count >= BaseCubicSpline.MinNumberOfNodes) { spline = new NotAKnotCubicSpline(xs, ys); } return(spline); }
private IList <double> ExecuteAll(ISecurity sec, IOptionSeries optSer) { if (sec == null) { return(Constants.EmptyListDouble); } IList <double> basePrices = CommonStreamExecute(m_variableId + "_basePrices", m_variableId + "_basePriceHistory", sec, m_repeatLastPx, true, false, new object[] { sec, optSer }); if (basePrices.Count > 0) { double px = basePrices[basePrices.Count - 1]; double displayValue = FixedValue.ConvertToDisplayUnits(m_valueMode, px); m_displayPrice.Value = displayValue; } return(new ReadOnlyCollection <double>(basePrices)); }