/// <summary>
        /// Проверка и заполнение параметров расчёта опциона.
        /// </summary>
        /// <param name="ip">Параметры инструмента (опциона).</param>
        /// <param name="oep">Парамметры расчёта опциона.</param>
        /// <returns>true если параметры валидны, false если расчёт по данным параметрам невозможен.</returns>
        private bool PopulateOptionEvaluationParams(InstrumentParams ip, ref OptionEvaluationParams oep)
        {
            #region Цена базового актива

            // Если не указана конкретная цена базового актива по которой нужно выполнять расчёт
            if (!oep.BaseActivePrice.HasValue)
            {
                // Пытаемся получить параметры фьючерса для данного опциона
                var ba = InstrumentParamsProvider.GetOptionFuturesParams(ip.Instrument);

                if (ba == null) // Если параметры фьючерса не получены - мы не можем выполнить расчёт
                    return false;

                oep.BaseActivePrice = ba.GetLastPriceOrSettlement(); // Получаем последнюю цену фьючерса
            }

            #endregion

            #region Время

            if (!oep.Time.HasValue)
            {
                // Если не указана точка во времени для которой нужно рассчитать цену опциона выполняем расчёт для текущего времени
                oep.Time = DateTime.Now;
            }

            #endregion

            #region Волатильность

            // Если не указана волатильность для которой нужно выполнять расчёт
            if (!oep.Vola.HasValue)
            {
                oep.Vola = (double)GetVola(ip); // Запрашиваем волатильность от этой же модели
            }

            #endregion

            #region Сдвиг волатильности

            // Если не задан сдвиг волатильности для которого нужно выполнять расчёт
            if (!oep.VolaShift.HasValue)
            {
                oep.VolaShift = 0;
            }

            #endregion

            return true; // Все параметры заполнены, можно производить расчёт
        }
        /// <summary>
        /// Расчёт цены опциона.
        /// </summary> 
        /// <param name="ip">
        /// Параметры инструмента (опциона).
        /// </param>
        /// <param name="oep">
        /// Параметры расчета опциона.
        /// </param>
        public double CalcPrice(InstrumentParams ip, OptionEvaluationParams oep)
        {
            // Проверяем переданные параметры расчёта опциона.
            if (!PopulateOptionEvaluationParams(ip, ref oep))
                return 0; // Расчёт по переданным параметрам невозможен.

            Debug.Assert(oep.BaseActivePrice != null, "oep.BaseActivePrice != null");
            Debug.Assert(oep.Time != null, "oep.Time != null");
            Debug.Assert(oep.Vola != null, "oep.Vola != null");
            Debug.Assert(oep.VolaShift != null, "oep.VolaShift != null");

            // Рассчитываем количество лет до экспирации опциона.
            var T = GetYearsTillExpiration(ip, oep.Time.Value);

            // Считаем цену опциона через модель Black-Scholes
            return BlackScholes.Price(ip.OptionType,
                                      oep.BaseActivePrice.Value,
                                      (double)ip.Strike,
                                      T,
                                      0, // TODO Добавить ставку в OptionEvaluationParams
                                      oep.Vola.Value + oep.VolaShift.Value);
        }
        /// <summary>
        /// Расчёт расширенных (теоретических) параметров опциона.
        /// </summary> 
        /// <param name="ip">
        /// Параметры инструмента (опциона).
        /// </param>
        /// <param name="oep">
        /// Параметры расчета опциона.
        /// </param>
        InstrumentCalculatedParams IModel.CalcPriceAndGreeks(InstrumentParams ip, OptionEvaluationParams oep)
        {
            // Создаём шаблон результата
            var rValue = new InstrumentCalculatedParams(ip);

            // Проверяем переданные параметры расчёта опциона.
            if (!PopulateOptionEvaluationParams(ip, ref oep))
                return rValue; // Расчёт по переданным параметрам невозможен.

            Debug.Assert(oep.BaseActivePrice != null, "oep.BaseActivePrice != null");
            Debug.Assert(oep.Time != null, "oep.Time != null");
            Debug.Assert(oep.Vola != null, "oep.Vola != null");
            Debug.Assert(oep.VolaShift != null, "oep.VolaShift != null");

            // Рассчитываем количество лет до экспирации опциона.
            var T = GetYearsTillExpiration(ip, oep.Time.Value);

            // Сохраняем цену базового актива для которой выполняется расчёт
            rValue.BaseAssetPrice = oep.BaseActivePrice.Value;
            // Сохраняем волатильность для которой выполняется расчёт
            rValue.TheorIV = oep.Vola.Value + oep.VolaShift.Value;
            // Сохраняем дату и время для которых выполняется расчёт
            // Этого свойства пока нет в публичной версии (будет в 12.8)
            //rValue.Time = oep.Time;

            // Считаем цену и греки через модель Black-Scholes
            var all = BlackScholes.CalcPriceAndGreeks(ip.OptionType,
                                                      oep.BaseActivePrice.Value,
                                                      (double)ip.Strike,
                                                      T,
                                                      0, // TODO Добавить ставку в OptionEvaluationParams
                                                      oep.Vola.Value + oep.VolaShift.Value);

            // Сохраняем цену и греки
            rValue.TheorPrice = all[0];
            rValue.Delta = all[1];
            rValue.Gamma = all[2];
            rValue.Vega = all[3];
            rValue.Theta = all[4];

            return rValue;
        }