Пример #1
0
        /// <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);
        }
Пример #2
0
        private IList <double> PrepareData(ISecurity sec, string expiryDate)
        {
            DateTime expiry;

            if ((!DateTime.TryParseExact(expiryDate, IvOnF.DateFormat, CultureInfo.InvariantCulture,
                                         DateTimeStyles.AssumeLocal, out expiry)) &&
                (!DateTime.TryParseExact(expiryDate, IvOnF.DateFormat + " HH:mm", CultureInfo.InvariantCulture,
                                         DateTimeStyles.AssumeLocal, out expiry)))
            {
                string msg = String.Format("[{0}.{1}.PrepareData] Unable to parse expiration date '{2}'. Expected date format '{3}'.",
                                           Context.Runtime.TradeName, GetType().Name, expiryDate, IvOnF.DateFormat);
                m_context.Log(msg, MessageType.Warning, true);
                return(Constants.EmptyListDouble);
            }

            //// и тут я понял, что дату экспирации в любом случае надо задавать руками...
            //string cashKey = typeof(IvOnF).Name + "_ivExchangeSigmas_" + sec.Symbol + "_" +
            //    expiryDate.Replace(':', '-');
            string skewKey = IvOnF.GetSkewCashKey(sec.Symbol, expiry, SkewMode, DistanceMode);
            Dictionary <DateTime, double> ivSkews = null;

            try
            {
                object globalObj = Context.LoadGlobalObject(skewKey, true);
                ivSkews = globalObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (ivSkews == null)
                {
                    var container = globalObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        ivSkews = container.Content as Dictionary <DateTime, double>;
                    }
                }
            }
            catch (NotSupportedException nse)
            {
                string fName = "", path = "";
                if (nse.Data["fName"] != null)
                {
                    fName = nse.Data["fName"].ToString();
                }
                if (nse.Data["path"] != null)
                {
                    path = nse.Data["path"].ToString();
                }
                string msg = String.Format("[{0}.PrepareData] {1} when loading 'ivSkews' from global cache. cashKey: {2}; Message: {3}\r\n\r\nfName: {4}; path: {5}\r\n\r\n{6}",
                                           GetType().Name, nse.GetType().FullName, skewKey, nse.Message, fName, path, nse);
                m_context.Log(msg, MessageType.Warning, true);
            }
            catch (Exception ex)
            {
                string msg = String.Format("[{0}.PrepareData] {1} when loading 'ivSkews' from global cache. cashKey: {2}; Message: {3}\r\n\r\n{4}",
                                           GetType().Name, ex.GetType().FullName, skewKey, ex.Message, ex);
                m_context.Log(msg, MessageType.Warning, true);
            }

            if (ivSkews == null)
            {
                // Данного ключа в глобальном кеше нет? Тогда выход.
                // [{0}.PrepareData] There is no Skew ATM in global cache. Probably, you have to start agent 'Collect IV (ALL)' for security '{1}'.
                string msg = RM.GetStringFormat("OptHandlerMsg.GlobalSkewOnF.CacheNotFound", GetType().Name, expiryDate, sec);
                if (m_context.Runtime.IsAgentMode && (!m_ignoreCacheError))
                {
                    throw new ScriptException(msg); // PROD-4624 - Андрей велит кидать исключение.
                }
                bool isExpired = true;
                if (m_context.Runtime.IsAgentMode)
                {
                    int      amount = sec.Bars.Count;
                    DateTime today  = (amount > 0) ? sec.Bars[amount - 1].Date : new DateTime();
                    isExpired = expiry.Date.AddDays(1) < today.Date;
                }
                // А если в режиме лаборатории, тогда только жалуемся и продолжаем.
                m_context.Log(msg, MessageType.Warning, !isExpired); // Если серия уже умерла, пишем только в локальный лог
                return(Constants.EmptyListDouble);
            }

            List <double> res = new List <double>();

            int len = sec.Bars.Count;

            if (len <= 0)
            {
                return(res);
            }

            int    oldResLen = res.Count;
            double prevSkew  = Double.NaN;

            for (int j = oldResLen; j < len; j++)
            {
                DateTime now = sec.Bars[j].Date;
                double   skew;
                if (ivSkews.TryGetValue(now, out skew) && (!DoubleUtil.IsNaN(skew)))
                {
                    prevSkew = skew;
                    res.Add(skew);
                }
                else
                {
                    if (m_repeatLastIv)
                    {
                        if (!Double.IsNaN(prevSkew))
                        {
                            skew = prevSkew;
                        }
                        else
                        {
                            skew = Constants.NaN;
                            if (j == 0)
                            {
                                #region Отдельно обрабатываю нулевой бар
                                double   tmp      = Double.NaN;
                                DateTime foundKey = new DateTime(1, 1, 1);
                                // [2016-01-19] Когда история становится слишком длинной, это может вызывать проблемы
                                // при итерировании в foreach. Потому что другой поток может в этот момент добавить новую точку в коллекцию.
                                int repeat = 7;
                                while (repeat > 0)
                                {
                                    tmp      = Double.NaN;
                                    foundKey = new DateTime(1, 1, 1);
                                    try
                                    {
                                        lock (ivSkews)
                                        {
                                            foreach (var kvp in ivSkews)
                                            {
                                                if (kvp.Key > now)
                                                {
                                                    continue;
                                                }

                                                if (foundKey < kvp.Key)
                                                {
                                                    foundKey = kvp.Key;
                                                    tmp      = kvp.Value;
                                                }
                                            }
                                        }
                                        repeat = -100;
                                    }
                                    catch (InvalidOperationException invOpEx)
                                    {
                                        repeat--;
                                        Thread.Sleep(10);
                                        if (repeat <= 0)
                                        {
                                            string msg = String.Format("[{0}.PrepareData] {1} when iterate through 'ivSkews'. cashKey: {2}; Message: {3}\r\n\r\n{4}",
                                                                       GetType().Name, invOpEx.GetType().FullName, skewKey, invOpEx.Message, invOpEx);
                                            m_context.Log(msg, MessageType.Warning, true);
                                            throw;
                                        }
                                    }
                                }

                                if ((foundKey.Year > 1) && DoubleUtil.IsPositive(tmp))
                                {
                                    skew     = tmp;
                                    prevSkew = skew;
                                }
                                #endregion Отдельно обрабатываю нулевой бар
                            }
                        }
                        res.Add(skew);
                    }
                    else
                    {
                        res.Add(Constants.NaN);
                    }
                }
            }

            return(res);
        }