/// <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> internal static bool TryEstimateTheta(PositionsManager posMan, IOptionStrikePair[] pairs, InteractiveSeries smile, NumericalGreekAlgo greekAlgo, double f, double timeToExpiry, double tStep, out double rawTheta) { rawTheta = 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 t1 = (timeToExpiry - tStep > Double.Epsilon) ? (timeToExpiry - tStep) : (0.5 * timeToExpiry); double cash1 = 0, pnl1 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect1 = true; { // TODO: фьюч на даёт вклад в тету??? //SingleSeriesProfile.GetBasePnl(posMan, optSer.UnderlyingAsset, optSer.UnderlyingAsset.Bars.Count - 1, f, out cash1, out pnl1); //// 1. Изменение положения БА //InteractiveSeries actualSmile = SingleSeriesProfile.GetActualSmile(smile, greekAlgo, f); SmileInfo actualSmile; // 1. Изменение положения БА actualSmile = SingleSeriesProfile.GetActualSmile(sInfo, greekAlgo, f); // 2. Изменение времени // ВАЖНО: нормальный алгоритм сдвига улыбки во времени будет в платной версии "Пакета Каленковича" actualSmile = SingleSeriesProfile.GetSmileAtTime(actualSmile, NumericalGreekAlgo.FrozenSmile, t1); for (int j = 0; j < pairs.Length; j++) { IOptionStrikePair pair = pairs[j]; double pairPnl, pairCash; //double putPx = FinMath.GetOptionPrice(f, pair.Strike, dT, sigma.Value, 0, false); //SingleSeriesProfile.GetPairPnl(posMan, actualSmile, pair, f, t1, out pairCash, out pairPnl); pnlIsCorrect1 &= SingleSeriesProfile.TryGetPairPnl(posMan, actualSmile, pair, f, t1, out pairCash, out pairPnl); cash1 += pairCash; pnl1 += pairPnl; } } double t2 = timeToExpiry + tStep; double cash2 = 0, pnl2 = 0; // Флаг того, что ПНЛ по всем инструментам был расчитан верно bool pnlIsCorrect2 = true; { // фьюч на даёт вклад в вегу //SingleSeriesProfile.GetBasePnl(posMan, optSer.UnderlyingAsset, optSer.UnderlyingAsset.Bars.Count - 1, f, out cash2, out pnl2); //// 1. Изменение положения БА //InteractiveSeries actualSmile = SingleSeriesProfile.GetActualSmile(smile, greekAlgo, f); SmileInfo actualSmile; // 1. Изменение положения БА actualSmile = SingleSeriesProfile.GetActualSmile(sInfo, greekAlgo, f); // 2. Изменение времени // ВАЖНО: нормальный алгоритм сдвига улыбки во времени будет в платной версии "Пакета Каленковича" actualSmile = SingleSeriesProfile.GetSmileAtTime(actualSmile, NumericalGreekAlgo.FrozenSmile, t2); for (int j = 0; j < pairs.Length; j++) { IOptionStrikePair pair = pairs[j]; double pairPnl, pairCash; //double putPx = FinMath.GetOptionPrice(f, pair.Strike, dT, sigma.Value, 0, false); //SingleSeriesProfile.GetPairPnl(posMan, actualSmile, pair, f, t2, out pairCash, out pairPnl); pnlIsCorrect2 &= SingleSeriesProfile.TryGetPairPnl(posMan, actualSmile, pair, f, t2, out pairCash, out pairPnl); cash2 += pairCash; pnl2 += pairPnl; } } if (pnlIsCorrect1 && pnlIsCorrect2) { rawTheta = ((cash2 + pnl2) - (cash1 + pnl1)) / (t2 - t1); // Переворачиваю тету, чтобы жить в календарном времени rawTheta = -rawTheta; return(true); } else { return(false); } }