Пример #1
0
        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>
        /// Тета будет иметь размерность 'пункты за год'.
        /// Обычно же опционщики любят смотреть размерность 'пункты за день'.
        /// Поэтому полученное сырое значение ещё надо делить на количество дней в году.
        /// (Эквивалентно умножению на интересующий набег времени для получения дифференциала).
        /// </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>
        /// Вега будет иметь размерность 'пункты за 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);
            }
        }
Пример #4
0
        internal static bool TryEstimateDelta(double putQty, double callQty, IOptionSeries optSer, IOptionStrikePair pair,
                                              InteractiveSeries smile, NumericalGreekAlgo greekAlgo,
                                              double f, double dF, double timeToExpiry, double riskFreeRate, out double rawDelta)
        {
            rawDelta = Double.NaN;

            if (timeToExpiry < Double.Epsilon)
            {
                throw new ArgumentOutOfRangeException("timeToExpiry", "timeToExpiry must be above zero. timeToExpiry:" + timeToExpiry);
            }

            SmileInfo sInfo = smile.Tag as SmileInfo;

            double pnl1 = 0;
            // Флаг того, что ПНЛ по всем инструментам был расчитан верно
            bool pnlIsCorrect1 = true;
            {
                if (sInfo != null)
                {
                    SmileInfo actualSmile = SingleSeriesProfile.GetActualSmile(sInfo, greekAlgo, f - dF);

                    double pairPnl;
                    pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPrice(
                        putQty, callQty, actualSmile, pair, f - dF, timeToExpiry, riskFreeRate, out pairPnl);
                    pnl1 += pairPnl;
                }
                else
                {
                    // PROD-5746 -- Убираю использование старого неэффективного кода
                    pnlIsCorrect1 = false;

                    Contract.Assert(pnlIsCorrect1, $"[{nameof(OptionsBoardNumericalDelta)}.{nameof(TryEstimateDelta)}] #1 Каким образом получили неподготовленную улыбку? (sInfo == null)");

                    //InteractiveSeries actualSmile = SingleSeriesProfile.GetActualSmile(smile, greekAlgo, f - dF);

                    //double pairPnl;
                    //pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPrice(
                    //    putQty, callQty, actualSmile, pair, f - dF, timeToExpiry, riskFreeRate, out pairPnl);
                    //pnl1 += pairPnl;
                }
            }

            double pnl2 = 0;
            // Флаг того, что ПНЛ по всем инструментам был расчитан верно
            bool pnlIsCorrect2 = true;

            {
                if (sInfo != null)
                {
                    SmileInfo actualSmile = SingleSeriesProfile.GetActualSmile(sInfo, greekAlgo, f + dF);

                    double pairPnl;
                    pnlIsCorrect2 &= SingleSeriesProfile.TryGetPairPrice(
                        putQty, callQty, actualSmile, pair, f + dF, timeToExpiry, riskFreeRate, out pairPnl);
                    pnl2 += pairPnl;
                }
                else
                {
                    // PROD-5746 -- Убираю использование старого неэффективного кода
                    pnlIsCorrect2 = false;

                    Contract.Assert(pnlIsCorrect2, $"[{nameof(OptionsBoardNumericalDelta)}.{nameof(TryEstimateDelta)}] #2 Каким образом получили неподготовленную улыбку? (sInfo == null)");

                    //InteractiveSeries actualSmile = SingleSeriesProfile.GetActualSmile(smile, greekAlgo, f + dF);

                    //double pairPnl;
                    //pnlIsCorrect2 &= SingleSeriesProfile.TryGetPairPrice(
                    //    putQty, callQty, actualSmile, pair, f + dF, timeToExpiry, riskFreeRate, out pairPnl);
                    //pnl2 += pairPnl;
                }
            }

            if (pnlIsCorrect1 && pnlIsCorrect2)
            {
                //rawDelta = ((cash2 + pnl2) - (cash1 + pnl1)) / 2.0 / dF;
                rawDelta = (pnl2 - pnl1) / 2.0 / dF;
                return(true);
            }
            else
            {
                return(false);
            }
        }