/// <summary> /// Делим Тету (размерности 'пунктов за год') на число дней в году с учетом конкретного алгоритма расчета времени /// </summary> internal static double RescaleThetaToDays(TimeRemainMode tRemainMode, double rawTheta) { double res; switch (tRemainMode) { case TimeRemainMode.PlainCalendar: res = rawTheta / TimeToExpiry.DaysInYearPlainCalendar; break; case TimeRemainMode.PlainCalendarWithoutHolidays: res = rawTheta / TimeToExpiry.DaysInYearPlainCalendarWithoutHolidays; break; case TimeRemainMode.PlainCalendarWithoutWeekends: res = rawTheta / TimeToExpiry.DaysInYearPlainCalendarWithoutWeekends; break; case TimeRemainMode.RtsTradingTime: res = rawTheta / TimeToExpiry.DaysInYearRts; break; case TimeRemainMode.LiquidProRtsTradingTime: res = rawTheta / TimeToExpiry.DaysInYearLiquidProRts; break; default: throw new NotImplementedException("tRemainMode: " + tRemainMode); } return(res); }
/// <summary> /// Вычисление нескольких видов наклона улыбки и обновление исторической серии, /// которая потенциально может быть сохранена в глобальный кеш. /// При записи в кеш серия помещается в NotClearableContainer, чтобы выживать при очистке памяти. /// </summary> public static bool TryCalcAndWriteSkews(IContext context, NotAKnotCubicSpline smileSpline, bool useGlobal, bool allowGlobalWrite, int savePeriod, string futSymbol, DateTime optExpiry, double futPx, DateTime lastBarDate, TimeRemainMode tRemainMode, double plainTimeAsYears, double timeAsYears) { bool successSkew = false; var splineD1 = smileSpline.DeriveD1(); if (splineD1.TryGetValue(futPx, out var skewAtm)) { //string symbol = optSer.UnderlyingAsset.Symbol; // А. Записываем в Глобальный Кеш РАЗМЕРНЫЙ наклон (модель времени неважна) { string skewKey = IvOnF.GetSkewCashKey(futSymbol, optExpiry, SmileSkewMode.RawSkew, TimeRemainMode.PlainCalendar); var ivSkews = LoadOrCreateHistoryDict(context, useGlobal, skewKey); // Это просто запись на диск. К успешности вычисления наклона successSkew отношения не имеет successSkew = TryWrite(context, useGlobal, allowGlobalWrite, savePeriod, skewKey, ivSkews, lastBarDate, skewAtm); } // В. Записываем в Глобальный Кеш БЕЗРАЗМЕРНЫЙ наклон В БИРЖЕВОМ ВРЕМЕНИ (PlainCalendar) { double dSigmaDxExchange = SmileImitation5.GetDSigmaDx(futPx, plainTimeAsYears, skewAtm, 0); if (!DoubleUtil.IsNaN(dSigmaDxExchange)) { string skewKey = IvOnF.GetSkewCashKey(futSymbol, optExpiry, SmileSkewMode.ExchangeSkew, TimeRemainMode.PlainCalendar); var ivSkews = LoadOrCreateHistoryDict(context, useGlobal, skewKey); // Это просто запись на диск. К успешности вычисления наклона successSkew отношения не имеет successSkew = TryWrite(context, useGlobal, allowGlobalWrite, savePeriod, skewKey, ivSkews, lastBarDate, dSigmaDxExchange); } } // Д. Записываем в Глобальный Кеш БЕЗРАЗМЕРНЫЙ наклон В НАШЕМ ВРЕМЕНИ (в соответствии с tRemainMode) { double dSigmaDxRescaled = SmileImitation5.GetDSigmaDx(futPx, timeAsYears, skewAtm, 0); if (!DoubleUtil.IsNaN(dSigmaDxRescaled)) { string skewKey = IvOnF.GetSkewCashKey(futSymbol, optExpiry, SmileSkewMode.RescaledSkew, tRemainMode); var ivSkews = LoadOrCreateHistoryDict(context, useGlobal, skewKey); // Это просто запись на диск. К успешности вычисления наклона successSkew отношения не имеет successSkew = TryWrite(context, useGlobal, allowGlobalWrite, savePeriod, skewKey, ivSkews, lastBarDate, dSigmaDxRescaled); } } } // End if (splineD1.TryGetValue(futPx, out var skewAtm)) return(successSkew); }
/// <summary> /// Ключ Глобального Кеша для хранения БИРЖЕВОГО НАКЛОНА на-деньгах /// </summary> public static string GetSkewCashKey(string baseSecuritySymbol, DateTime expiry, SmileSkewMode skewMode, TimeRemainMode tRemainMode) { string cashKey; if (skewMode == SmileSkewMode.RawSkew) { // Сырой размерный наклон ничего не знает о времени cashKey = typeof(IvOnF).Name + "_ivExchangeSkews_" + skewMode + "_" + baseSecuritySymbol + "_" + expiry.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); } else { // Безразмерный наклон обязан знать про время. // TODO: И, по-хорошему, про форму. Но это можно отложить пока что. cashKey = typeof(IvOnF).Name + "_ivExchangeSkews_" + skewMode + "_" + tRemainMode + "_" + baseSecuritySymbol + "_" + expiry.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); } return(String.Intern(cashKey)); }
/// <summary> /// Ключ Глобального Кеша для хранения БИРЖЕВОЙ волатильности на-деньгах /// </summary> public static string GetCashKey(string baseSecuritySymbol, DateTime expiry, bool rescaleTime, TimeRemainMode tRemainMode) { string cashKey; if (rescaleTime) { // Если мы перемасштабируем время, то волу надо хранить в кеше с другим названием // (в зависимости от алгоритма)! cashKey = String.Format(CultureInfo.InvariantCulture, "{0}_ivExchangeSigmas_{1}_{2}_{3}", typeof(IvOnF).Name, tRemainMode, baseSecuritySymbol, expiry.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture)); } else { cashKey = typeof(IvOnF).Name + "_ivExchangeSigmas_" + baseSecuritySymbol + "_" + expiry.ToString(IvOnF.DateFormat, CultureInfo.InvariantCulture); } return(String.Intern(cashKey)); }
/// <summary> /// Вернуть время между двумя датами в соответствии с заказанным алгоритмом расчета /// </summary> /// <param name="expiry">дата экспирации</param> /// <param name="now">текущая дата</param> /// <param name="tRemainMode">режим расчета</param> /// <param name="returnDays">возвращать в долях года или в долях дней</param> /// <param name="timeAsDays">время в долях дня</param> /// <param name="timeAsYears">время в долях года</param> /// <returns>время между двумя датами</returns> public static double GetDt(DateTime expiry, DateTime now, TimeRemainMode tRemainMode, bool returnDays, out double timeAsDays, out double timeAsYears) { double days, daysInYear; double partOfDayForTrading; switch (tRemainMode) { case TimeRemainMode.PlainCalendar: { TimeSpan ts = expiry - now; days = ts.TotalDays; partOfDayForTrading = 1; daysInYear = DaysInYearPlainCalendar; } break; case TimeRemainMode.PlainCalendarWithoutWeekends: { TimeSpan ts = OptionUtils.GetDtWithoutWeekendsSlow(expiry, now); days = ts.TotalDays; partOfDayForTrading = 1; daysInYear = DaysInYearPlainCalendarWithoutWeekends; } break; case TimeRemainMode.PlainCalendarWithoutHolidays: { TimeSpan ts = OptionUtils.GetDtWithoutHolidaysSlow(expiry, now); days = ts.TotalDays; partOfDayForTrading = 1; daysInYear = DaysInYearPlainCalendarWithoutHolidays; } break; case TimeRemainMode.RtsTradingTime: { TimeSpan ts = OptionUtils.GetDtRtsTradingTime(expiry, now); days = ts.TotalDays; partOfDayForTrading = ((double)OptionUtils.TradingMinutesInDayRts) / (double)OptionUtils.MinutesInDay; daysInYear = DaysInYearRts; } break; case TimeRemainMode.LiquidProRtsTradingTime: { double tradingDaysInYear; double dT = OptionUtils.GetDtLiquidProRtsTradingTime(expiry, now, out tradingDaysInYear); timeAsDays = dT * tradingDaysInYear; timeAsYears = dT; if (returnDays) { return(timeAsDays); } else { return(timeAsYears); } } //break; default: throw new NotImplementedException("tRemainMode:" + tRemainMode); } timeAsDays = days / partOfDayForTrading; timeAsYears = days / daysInYear; if (returnDays) { return(timeAsDays); } else { return(timeAsYears); } }