Example #1
0
        /// <summary>
        /// Записываем в локальный кеш признак и дату того,
        /// что данный блок уже работал правильно (например, был полностью готов к торговле)
        /// </summary>
        /// <param name="now">время выставления состояния</param>
        /// <param name="state">состояние</param>
        protected virtual void SetHandlerInitialized(DateTime now, bool state = true)
        {
            string key       = "Initialized_" + m_variableId;
            var    tuple     = Tuple.Create(now, state);
            var    container = new NotClearableContainer <Tuple <DateTime, bool> >(tuple);

            // Специально без записи на диск, чтобы после перезапуска ТСЛаб объект был пуст
            m_context.StoreObject(key, container, false);
        }
Example #2
0
        /// <summary>
        /// Загрузить из кеша (локального ИЛИ глобального) серию чисел во времени
        /// </summary>
        /// <param name="context">контекст кубика</param>
        /// <param name="useGlobalCache">флаг глобальный или локальный кеш</param>
        /// <param name="cashKey">ключ кеша</param>
        /// <returns>серия из кеша, либо новый объект (который уже помещен в этот кеш)</returns>
        public static Dictionary <DateTime, double> LoadOrCreateHistoryDict(IContext context, bool useGlobalCache, string cashKey)
        {
            Dictionary <DateTime, double> history;

            if (useGlobalCache)
            {
                object globalObj = context.LoadGlobalObject(cashKey, true);
                history = globalObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (history == null)
                {
                    var container = globalObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        history = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (history == null)
                {
                    history = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(history);
                    context.StoreGlobalObject(cashKey, container, true);
                }
            }
            else
            {
                object locObj = context.LoadObject(cashKey);
                history = locObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (history == null)
                {
                    var container = locObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        history = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (history == null)
                {
                    history = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(history);
                    context.StoreObject(cashKey, container);
                }
            }

            return(history);
        }
Example #3
0
 protected virtual void SaveHistory(Dictionary <DateTime, T> history, string cashKey,
                                    bool useGlobalCacheForHistory, bool isStorage = false)
 {
     lock (history)
     {
         var data = new NotClearableContainer <Dictionary <DateTime, T> >(history);
         if (useGlobalCacheForHistory)
         {
             m_context.StoreGlobalObject(cashKey, data, isStorage);
         }
         else
         {
             m_context.StoreObject(cashKey, data, isStorage);
         }
         m_privateCache = null;
     }
 }
Example #4
0
        /// <summary>
        /// Обновление исторической серии, которая потенциально может быть сохранена в глобальный кеш.
        /// При записи в кеш серия помещается в NotClearableContainer, чтобы выживать при очистке памяти.
        /// </summary>
        /// <returns>
        /// true, если новое значение было фактически помещено в серию;
        /// false возникает, если запись в глобальный кеш блокирована флагом allowGlobalWrite
        /// </returns>
        public static bool TryWrite(IContext context, bool useGlobal, bool allowGlobalWrite, int savePeriod,
                                    string cashKey, Dictionary <DateTime, double> series, DateTime now, double val)
        {
            if (useGlobal)
            {
                if (allowGlobalWrite)
                {
                    series[now] = val;
                    if (series.Count % savePeriod == 0)
                    {
                        var container = new NotClearableContainer(series);
                        context.StoreGlobalObject(cashKey, container, true);
                    }
                    return(true);
                }
            }
            else
            {
                series[now] = val;
                return(true);
            }

            return(false);
        }
Example #5
0
        /// <summary>
        /// Извлечь из локального кеша историю значений данного индикатора.
        /// Если ее нет, создать и сразу поместить туда.
        /// </summary>
        /// <returns>история значений данного индикатора</returns>
        private List <double> PreparePositionQtys()
        {
            // [2019-01-30] Перевожу на использование NotClearableContainer (PROD-6683)
            List <double> positionQtys;
            string        key       = VariableId + "_positionQtys";
            var           container = m_context.LoadObject(key) as NotClearableContainer <List <double> >;

            if (container != null)
            {
                positionQtys = container.Content;
            }
            else
            {
                positionQtys = m_context.LoadObject(key) as List <double>; // Старая ветка на всякий случай
            }
            if (positionQtys == null)
            {
                positionQtys = new List <double>();
                container    = new NotClearableContainer <List <double> >(positionQtys);
                m_context.StoreObject(key, container);
            }

            return(positionQtys);
        }
Example #6
0
        public IList <double> Execute(ISecurity sec)
        {
            //Context.Log(String.Format("[Heartbeat.Execute ( ID:{0} )] I'm checking timer settings.", m_id), MessageType.Warning, false);

            // PROD-5496 - В режиме оптимизации отключаюсь
            if (Context.IsOptimization)
            {
                return(Constants.EmptyListDouble);
            }

            CallState timerState = null;
            string    cashKey    = VariableId + "_timerState";

            {
                object localObj = Context.LoadObject(cashKey, false);
                timerState = localObj as CallState;
                // PROD-3970 - 'Важный' объект
                if (timerState == null)
                {
                    var container = localObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        timerState = container.Content as CallState;
                    }
                }
            }

            //m_timer = Context.LoadObject(VariableId + "m_timer") as IThreadingTimerProfiler;
            if (timerState == null)
            {
                string msg = String.Format("[Heartbeat.Execute ( ID:{0} )] Preparing new timer for agent '{1}'...",
                                           m_id, Context.Runtime.TradeName);
                Context.Log(msg, MessageType.Info, false);

                var secInfo = new PositionsManager.SecInfo(sec.SecurityDescription);
                timerState = new CallState(m_id, Context, secInfo, m_onlyAtTradingSession);
                var timer = new ThreadingTimerProfiler(Recalculate, timerState, m_delayMs, Timeout.Infinite);
                // Обязательно дозаполняем ссылку на таймер
                timerState.Timer = timer;

                var container = new NotClearableContainer(timerState);
                Context.StoreObject(cashKey, container, false);
            }
            else if (timerState.Timer == null)
            {
                // PROD-5427 - Добавляю счетчик этого аварийного события и логгирую
                int problemCounter = 0;
                if (s_problemCounters.ContainsKey(Context.Runtime.TradeName))
                {
                    problemCounter = s_problemCounters[Context.Runtime.TradeName];
                }

                s_problemCounters[Context.Runtime.TradeName] = Interlocked.Increment(ref problemCounter);

                string msg = String.Format("[Heartbeat.Execute ( ID:{0} )] Timer is null in agent '{1}'. Problem counter: {2}",
                                           m_id, Context.Runtime.TradeName, problemCounter);
                Context.Log(msg, MessageType.Warning, false);

                if (problemCounter > 3)
                {
                    // Если проблема систематически повторяется -- выбрасываю ассерт для дальнейшего анализа ситуации
                    Contract.Assert(timerState.Timer != null, msg);
                }
            }
            else
            {
                //Contract.Assert(timerState.Timer != null, "Почему вдруг (timerState.Timer==null) ??");

                // Если при изменении скрипта пересоздается агент, то контекст становится невалидным?
                if (Object.ReferenceEquals(Context, timerState.CallContext))
                {
                    // Если контекст совпадает, то обновляем режим работы...
                    timerState.OnlyAtTradingSession = m_onlyAtTradingSession;
                    // и перезапускаем таймер
                    try
                    {
                        timerState.Timer.Change(m_delayMs, Timeout.Infinite);
                        // PROD-5427 - При штатной работе блока обнуляю счетчик проблем
                        s_problemCounters[Context.Runtime.TradeName] = 0;
                    }
                    catch (ObjectDisposedException)
                    {
                        // Если таймер уже убит, то надо создать новый
                        timerState.Timer = null;
                        timerState       = null;

                        string msg = String.Format("[Heartbeat.Execute ( ID:{0} )] Replacing DISPOSED timer for agent '{1}'...",
                                                   m_id, Context.Runtime.TradeName);
                        Context.Log(msg, MessageType.Warning, false);

                        // Создаём новый таймер. При этом используем НОВЫЙ m_id
                        var secInfo = new PositionsManager.SecInfo(sec.SecurityDescription);
                        timerState = new CallState(m_id, Context, secInfo, m_onlyAtTradingSession);
                        var timer = new ThreadingTimerProfiler(Recalculate, timerState, m_delayMs, Timeout.Infinite);
                        // Обязательно дозаполняем ссылку на таймер
                        timerState.Timer = timer;

                        var container = new NotClearableContainer(timerState);
                        Context.StoreObject(cashKey, container, false);
                    }
                }
                else
                {
                    // Если по какой-то причине изменился контекст, то создаём новый таймер...
                    timerState.Timer.Dispose();
                    timerState.Timer = null;
                    timerState       = null;

                    string msg = String.Format("[Heartbeat.Execute ( ID:{0} )] Replacing timer for agent '{1}'...",
                                               m_id, Context.Runtime.TradeName);
                    Context.Log(msg, MessageType.Warning, false);

                    // Создаём новый таймер. При этом используем НОВЫЙ m_id
                    var secInfo = new PositionsManager.SecInfo(sec.SecurityDescription);
                    timerState = new CallState(m_id, Context, secInfo, m_onlyAtTradingSession);
                    var timer = new ThreadingTimerProfiler(Recalculate, timerState, m_delayMs, Timeout.Infinite);
                    // Обязательно дозаполняем ссылку на таймер
                    timerState.Timer = timer;

                    var container = new NotClearableContainer(timerState);
                    Context.StoreObject(cashKey, container, false);
                }
            }

            int len = Context.BarsCount;

            double[] res = Context.GetArray <double>(len);
            if (len > 0)
            {
                res[len - 1] = m_id;
            }

            return(res);
        }
Example #7
0
        /// <summary>
        /// Метод под флаг TemplateTypes.SECURITY, чтобы подключаться к источнику-БА
        /// </summary>
        public IList <double> Execute(ISecurity sec)
        {
            if (sec == null)
            {
                return(Constants.EmptyListDouble);
            }

            Dictionary <DateTime, double> hvSigmas;

            #region Get cache
            int    barLengthInSeconds = (int)sec.IntervalInstance.ToSeconds();
            string cashKey            = GetGlobalCashKey(sec.Symbol, false, m_useAllData, barLengthInSeconds, m_annualizingMultiplier, m_period);
            if (UseGlobalCache)
            {
                object globalObj = Context.LoadGlobalObject(cashKey, true);
                hvSigmas = globalObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = globalObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreGlobalObject(cashKey, container, true);
                }
            }
            else
            {
                object locObj = Context.LoadObject(cashKey);
                hvSigmas = locObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = locObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreObject(cashKey, container);
                }
            }
            #endregion Get cache

            List <double> historySigmas = LocalHistory;

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                historySigmas.Clear();
            }

            int len = Context.BarsCount;
            // Локальный ключ можно всегда формировать вместе с периодом!
            string logsLocObjKey = VariableId + "_logs_" + m_period;
            object logsLocObj    = m_context.LoadObject(logsLocObjKey);
            LinkedList <KeyValuePair <DateTime, double> > logs = logsLocObj as LinkedList <KeyValuePair <DateTime, double> >;
            #region Get cache
            // PROD-3970 - 'Важный' объект
            if (logs == null)
            {
                var container = logsLocObj as NotClearableContainer;
                if ((container != null) && (container.Content != null))
                {
                    logs = container.Content as LinkedList <KeyValuePair <DateTime, double> >;
                }
            }
            if (logs == null)
            {
                logs = new LinkedList <KeyValuePair <DateTime, double> >();
                var container = new NotClearableContainer(logs);
                m_context.StoreObject(logsLocObjKey, container);
            }
            #endregion Get cache

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                logs.Clear();
            }

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

            // Типа, кеширование?
            for (int j = historySigmas.Count; j < len; j++)
            {
                IDataBar bar;
                try
                {
                    // Наблюдал на реале странную картину (ВО ВРЕМЯ КЛИРИНГА!):
                    // Context.BarsCount == 3843 && sec.Bars.Count == 3842
                    bar = sec.Bars[j];
                    // если бар технический (то есть имеет нулевой объём), пропускаем его
                    // 2017-04-26 - На эксанте при запросе истории все бары имеют нулевой объём, но при этом большинство из них являются нормальными:
                    //              имеют ненулевой размах и осмысленные значения открытия/закрытия
                    if ((bar.Volume <= Double.Epsilon) && (DoubleUtil.AreClose(bar.High, bar.Low)))
                    {
                        // пишу NaN в такой ситуации
                        historySigmas.Add(Constants.NaN);
                        continue;
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    // Перехватываю aorEx и пишу NaN в такой ситуации
                    historySigmas.Add(Constants.NaN);
                    continue;
                }

                DateTime t  = bar.Date;
                double   v  = bar.Close;
                double   ln = Math.Log(v);

                Contract.Assert(logs != null, "Каким образом переменная logs оказалась null?");
                logs.AddLast(new KeyValuePair <DateTime, double>(t, ln));

                double hv;
                if (TryEstimateHv(
                        logs, m_period, barLengthInSeconds, m_annualizingMultiplier,
                        m_useAllData, out hv))
                {
                    double vol = hv;
                    historySigmas.Add(vol);

                    lock (hvSigmas)
                    {
                        hvSigmas[t] = vol;
                    }
                }
                else
                {
                    historySigmas.Add(Constants.NaN);
                }
            }

            // Попытку записи в глобальный кеш делаю только в самом конце всех вычислений
            // для экономии времени на сериализацию и запись
            lock (hvSigmas)
            {
                if (sec.Bars.Count > len - 1)
                {
                    // Наблюдал на реале странную картину (ВО ВРЕМЯ КЛИРИНГА!):
                    // Context.BarsCount == 3760 && sec.Bars.Count == 3759
                    bool success = IvOnF.TryWrite(m_context, UseGlobalCache, AllowGlobalReadWrite, GlobalSavePeriod,
                                                  cashKey, hvSigmas, sec.Bars[len - 1].Date, historySigmas[historySigmas.Count - 1]);
                }

                return(new ReadOnlyCollection <double>(historySigmas));
            }
        }
Example #8
0
        /// <summary>
        /// Метод под флаг TemplateTypes.SECURITY, чтобы подключаться к источнику-БА
        /// </summary>
        public IList <double> Execute(ISecurity sec)
        {
            if (sec == null)
            {
                return(Constants.EmptyListDouble);
            }

            Dictionary <DateTime, double> hvSigmas;

            #region Get cache
            int    barLengthInSeconds = (int)sec.IntervalInstance.ToSeconds();
            string cashKey            = GetGlobalCashKey(sec.Symbol, false, m_useAllData, barLengthInSeconds, m_annualizingMultiplier);
            if (UseGlobalCache)
            {
                object globalObj = Context.LoadGlobalObject(cashKey, true);
                hvSigmas = globalObj as Dictionary <DateTime, double>;
                // 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = globalObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreGlobalObject(cashKey, container, true);
                }
            }
            else
            {
                object locObj = Context.LoadObject(cashKey);
                hvSigmas = locObj as Dictionary <DateTime, double>;
                // 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = locObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreObject(cashKey, container);
                }
            }
            #endregion Get cache

            List <double> historySigmas = LocalHistory;

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                historySigmas.Clear();
            }

            int    len        = Context.BarsCount;
            object logsLocObj = m_context.LoadObject(VariableId + "logs");
            LinkedList <KeyValuePair <DateTime, double> > logs = logsLocObj as LinkedList <KeyValuePair <DateTime, double> >;
            #region Get cache
            // 'Важный' объект
            if (logs == null)
            {
                var container = logsLocObj as NotClearableContainer;
                if ((container != null) && (container.Content != null))
                {
                    logs = container.Content as LinkedList <KeyValuePair <DateTime, double> >;
                }
            }
            if (logs == null)
            {
                logs = new LinkedList <KeyValuePair <DateTime, double> >();
                var container = new NotClearableContainer(logs);
                m_context.StoreObject(VariableId + "logs", container);
            }
            #endregion Get cache

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                logs.Clear();
            }

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

            // Кеширование
            for (int j = historySigmas.Count; j < len; j++)
            {
                IDataBar bar;
                try
                {
                    bar = sec.Bars[j];
                    // если бар технический (то есть имеет нулевой объём), пропускаем его
                    if ((bar.Volume <= Double.Epsilon) && (DoubleUtil.AreClose(bar.High, bar.Low)))
                    {
                        // пишу NaN в такой ситуации
                        historySigmas.Add(Constants.NaN);
                        continue;
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    // Перехватываю aorEx и пишу NaN в такой ситуации
                    historySigmas.Add(Constants.NaN);
                    continue;
                }

                DateTime t  = bar.Date;
                double   v  = bar.Close;
                double   ln = Math.Log(v);

                logs.AddLast(new KeyValuePair <DateTime, double>(t, ln));

                double hv;
                if (TryEstimateHv(
                        logs, m_period, barLengthInSeconds, m_annualizingMultiplier,
                        m_useAllData, out hv))
                {
                    double vol = hv;
                    historySigmas.Add(vol);

                    lock (hvSigmas)
                    {
                        hvSigmas[t] = vol;
                    }
                }
                else
                {
                    historySigmas.Add(Constants.NaN);
                }
            }

            // Попытку записи в глобальный кеш делаю только в самом конце всех вычислений
            // для экономии времени на сериализацию и запись
            lock (hvSigmas)
            {
                if (sec.Bars.Count > len - 1)
                {
                    bool success = IvOnF.TryWrite(m_context, UseGlobalCache, AllowGlobalReadWrite, GlobalSavePeriod,
                                                  cashKey, hvSigmas, sec.Bars[len - 1].Date, historySigmas[historySigmas.Count - 1]);
                }

                return(new ReadOnlyCollection <double>(historySigmas));
            }
        }
Example #9
0
        public IList <double> Execute(ISecurity sec)
        {
            //Context.Log(String.Format("[Heartbeat.Execute ( ID:{0} )] I'm checking timer settings.", m_id), MessageType.Warning, false);

            // PROD-5496 - В режиме оптимизации отключаюсь
            if (Context.IsOptimization)
            {
                return(Constants.EmptyListDouble);
            }
            var secrt = sec as ISecurityRt;

            if (secrt?.IsPortfolioActive != true)
            {
                return(Constants.EmptyListDouble);
            }

            TimerInfo timerState;
            string    cashKey = VariableId + "_timerState";

            {
                object localObj = Context.LoadObject(cashKey);
                timerState = localObj as TimerInfo;
                // PROD-3970 - 'Важный' объект
                if (timerState == null)
                {
                    if (localObj is NotClearableContainer container && container.Content != null)
                    {
                        timerState = container.Content as TimerInfo;
                    }
                }
            }

            if (timerState == null)
            {
                string msg = $"[RecalcScheduler({m_id})] Preparing new timer for agent '{Context.Runtime.TradeName}'...";
                Context.Log(msg);

                timerState = TimerInfo.Create(Context, secrt, RecalcTime);

                var container = new NotClearableContainer(timerState);
                Context.StoreObject(cashKey, container);
            }
            else if (timerState.Timer == null)
            {
                // PROD-5427 - Добавляю счетчик этого аварийного события и логгирую
                int problemCounter = 0;
                if (s_problemCounters.ContainsKey(Context.Runtime.TradeName))
                {
                    problemCounter = s_problemCounters[Context.Runtime.TradeName];
                }

                s_problemCounters[Context.Runtime.TradeName] = Interlocked.Increment(ref problemCounter);

                string msg =
                    $"[RecalcScheduler({m_id})] Timer is null in agent '{Context.Runtime.TradeName}'. Problem counter: {problemCounter}";
                Context.Log(msg, MessageType.Warning);

                if (problemCounter > 3)
                {
                    // Если проблема систематически повторяется -- выбрасываю ассерт для дальнейшего анализа ситуации
                    Contract.Assert(timerState.Timer != null, msg);
                }
            }
            else
            {
                // Если при изменении скрипта пересоздается агент, то контекст становится невалидным?
                if (!ReferenceEquals(Context, timerState.CallContext))
                {
                    // Если по какой-то причине изменился контекст, то создаём новый таймер...
                    string msg = $"[RecalcScheduler({m_id})] Replacing timer for agent '{Context.Runtime.TradeName}'...";
                    Context.Log(msg, MessageType.Warning);

                    // Создаём новый таймер. При этом используем НОВЫЙ m_id
                    timerState = TimerInfo.Create(Context, secrt, RecalcTime);
                    var container = new NotClearableContainer(timerState);
                    Context.StoreObject(cashKey, container);
                }
            }

            int len = Context.BarsCount;

            double[] res = Context.GetArray <double>(len);
            if (len > 0)
            {
                res[len - 1] = m_id;
            }

            return(res);
        }
Example #10
0
        private double Process(InteractiveSeries profile, double moneyness, int barNum)
        {
            // В данном случае намеренно возвращаю Double.NaN
            double failRes = Double.NaN;

            if (m_repeatLastValue)
            {
                failRes = Double.IsNaN(m_prevValue) ? Double.NaN : m_prevValue; // В данном случае намеренно возвращаю Double.NaN
            }
            Dictionary <DateTime, double> results;

            #region Get cache
            // [2019-01-30] Перевожу на использование NotClearableContainer (PROD-6683)
            string key       = m_variableId + "_results";
            var    container = m_context.LoadObject(key) as NotClearableContainer <Dictionary <DateTime, double> >;
            if (container != null)
            {
                results = container.Content;
            }
            else
            {
                results = m_context.LoadObject(key) as Dictionary <DateTime, double>; // Старая ветка на всякий случай
            }
            if (results == null)
            {
                string msg = String.Format(RM.GetString("OptHandlerMsg.GetValueAtm.CacheNotFound"),
                                           GetType().Name, key.GetHashCode());
                m_context.Log(msg, MessageType.Info);

                results   = new Dictionary <DateTime, double>();
                container = new NotClearableContainer <Dictionary <DateTime, double> >(results);
                m_context.StoreObject(key, container);
            }
            #endregion Get cache

            int len = m_context.BarsCount;
            if (len <= 0)
            {
                return(failRes);
            }

            // Вот так не работает. По всей видимости, это прямая индексация от утра
            //DateTime now = m_context.Runtime.GetBarTime(barNum);

            ISecurity sec = m_context.Runtime.Securities.FirstOrDefault();
            if ((sec == null) || (sec.Bars.Count <= barNum))
            {
                return(failRes);
            }

            DateTime now = sec.Bars[barNum].Date;
            if (results.TryGetValue(now, out double rawRes) &&
                (barNum < len - 1)) // !!! ВАЖНО !!! На последнем баре ВСЕГДА заново делаем вычисления
            {
                m_prevValue = rawRes;
                return(rawRes);
            }
            else
            {
                int barsCount = ContextBarsCount;
                if (barNum < barsCount - 1)
                {
                    // Если история содержит осмысленное значение, то оно уже содержится в failRes
                    return(failRes);
                }
                else
                {
                    #region Process last bar(s)
                    if (profile == null)
                    {
                        return(failRes);
                    }

                    SmileInfo profInfo = profile.GetTag <SmileInfo>();
                    if ((profInfo == null) || (profInfo.ContinuousFunction == null))
                    {
                        return(failRes);
                    }

                    double f  = profInfo.F;
                    double dT = profInfo.dT;
                    if (!DoubleUtil.IsPositive(f))
                    {
                        string msg = String.Format(RM.GetString("OptHandlerMsg.FutPxMustBePositive"), GetType().Name, f);
                        m_context.Log(msg, MessageType.Error);
                        // [GLSP-1557] В данном случае намеренно возвращаю Double.NaN, чтобы предотвратить распространение
                        //             заведомо неправильных данных по системе (их попадание в дельта-хеджер и т.п.).
                        return(Double.NaN);
                    }

                    if (!DoubleUtil.IsPositive(dT))
                    {
                        string msg = String.Format(RM.GetString("OptHandlerMsg.TimeMustBePositive"), GetType().Name, dT);
                        m_context.Log(msg, MessageType.Error);
                        // [GLSP-1557] В данном случае намеренно возвращаю Double.NaN, чтобы предотвратить распространение
                        //             заведомо неправильных данных по системе (их попадание в дельта-хеджер и т.п.).
                        return(Double.NaN);
                    }

                    double effectiveF;
                    if (DoubleUtil.IsZero(moneyness))
                    {
                        effectiveF = f;
                    }
                    else
                    {
                        effectiveF = f * Math.Exp(moneyness * Math.Sqrt(dT));
                    }
                    if (profInfo.ContinuousFunction.TryGetValue(effectiveF, out rawRes))
                    {
                        m_prevValue  = rawRes;
                        results[now] = rawRes;
                    }
                    else
                    {
                        if (barNum < len - 1)
                        {
                            // [GLSP-1557] Не последний бар? Тогда использую failRes
                            rawRes = failRes;
                        }
                        else
                        {
                            // [GLSP-1557] В данном случае намеренно возвращаю Double.NaN, чтобы предотвратить распространение
                            //             заведомо неправильных данных по системе (их попадание в дельта-хеджер и т.п.).
                            return(Double.NaN);
                        }
                    }
                    #endregion Process last bar(s)

                    m_result.Value = rawRes;
                    //m_context.Log(MsgId + ": " + m_result.Value, MessageType.Info, PrintInLog);

                    return(rawRes);
                }
            }
        }
Example #11
0
        /// <summary>
        /// Пытается угадать видимую область и если это получается результат складывает в локальный кеш
        /// </summary>
        private Rect PrepareVieportSettings(string seriesExpiry, double futPx, double dT, double sigma)
        {
            Rect rect;
            //string key = VariableId + KeySuffix + "_" + (seriesExpiry ?? "NULL");
            string key       = GetViewportCacheKey(this, seriesExpiry);
            var    container = Context.LoadObject(key) as NotClearableContainer <Rect>;

            // Проверка на ApplyVisualSettings нужна, чтобы безусловно поменять видимую область при нажатии на кнопку в UI
            if ((container != null) /*&& (container.Content != null)*/ && (!ApplyVisualSettings) &&
                DoubleUtil.IsPositive(container.Content.Width) && DoubleUtil.IsPositive(container.Content.Height))   // PROD-3901
            {
                rect = container.Content;
            }
            else
            {
                // PROD-5747 - Если контенер пуст, давайте сделаем в логе запись об этом?
                // Тогда будет понятно в какой момент он чистится.
                if ((container == null) /*|| (container.Content == null)*/ ||
                    (!DoubleUtil.IsPositive(futPx)) || (!DoubleUtil.IsPositive(sigma)))
                {
                    string expStr    = seriesExpiry ?? "NULL";
                    string tradeName = (m_context.Runtime?.TradeName ?? "NULL").Replace(Constants.HtmlDot, ".");
                    string msg       = String.Format(CultureInfo.InvariantCulture,
                                                     "[{0}.PrepareVieportSettings] Empty container. Key:'{1}'; futPx:{2}; dT:{3}; sigma:{4}; expiry:{5}; TradeName:'{6}'",
                                                     GetType().Name, key, futPx, dT, sigma, expStr, tradeName);
                    m_context.Log(msg, MessageType.Info, false);
                }
                else if ((container != null) /*&& (container.Content != null)*/ &&
                         ((!DoubleUtil.IsPositive(container.Content.Width)) ||
                          (!DoubleUtil.IsPositive(container.Content.Height))))
                {
                    string expStr    = seriesExpiry ?? "NULL";
                    string tradeName = (m_context.Runtime?.TradeName ?? "NULL").Replace(Constants.HtmlDot, ".");
                    string msg       = String.Format(CultureInfo.InvariantCulture,
                                                     "[{0}.PrepareVieportSettings] BAD RECT. Key:'{1}'; futPx:{2}; dT:{3}; sigma:{4}; expiry:{5}; TradeName:'{6}'; Width:{7}; Height:{8}",
                                                     GetType().Name, key, futPx, dT, sigma, expStr, tradeName, container.Content.Width, container.Content.Height);
                    m_context.Log(msg, MessageType.Info, false);
                }

                //// При самом первом запуске эмулирую нажатие кнопки Apply, чтобы заставить
                //// CanvasPane реагировать на мои настройки в Borders2.
                //ApplyVisualSettings = true;

                double width = (SigmaMult * sigma * Math.Sqrt(dT)) * futPx;
                // Общая ширина не менее 10% от futPx?
                //width = Math.Max(width, futPx * 0.05);

                double left = Math.Max(0, futPx - width);
                // Чтобы график был симметричен, ширину тоже подрезаю
                width = Math.Abs(futPx - left);
                double height = sigma * (m_verticalMultiplier - 1.0 / m_verticalMultiplier);
                rect = new Rect(futPx - width, sigma * m_verticalMultiplier, 2 * width, height);

                // PROD-5747 - Сохранять область в кеш можно только если прямоугольник имеет нормальные размеры
                if (DoubleUtil.IsPositive(rect.Width) && DoubleUtil.IsPositive(rect.Height))
                {
                    // При самом первом запуске эмулирую нажатие кнопки Apply, чтобы заставить
                    // CanvasPane реагировать на мои настройки в Borders2.
                    ApplyVisualSettings = true;

                    container = new NotClearableContainer <Rect>(rect);
                    Context.StoreObject(key, container);
                }
            }
            return(rect);
        }
Example #12
0
        /// <summary>
        /// \~english Get history of previous values
        /// \~russian История предыдущих значений
        /// </summary>
        /// <param name="cashKey">ключ кеша</param>
        /// <param name="useGlobalCacheForHistory">искать серию исторических данных в Глобальном Кеше?</param>
        /// <param name="fromStorage">читать с диска</param>
        /// <returns>коллекция с историей</returns>
        // ReSharper disable once VirtualMemberNeverOverriden.Global
        protected virtual Dictionary <DateTime, T> GetHistory(string cashKey, bool useGlobalCacheForHistory, bool fromStorage = false)
        {
            if ((m_context == null) || String.IsNullOrWhiteSpace(cashKey))
            {
                return(null);
            }

            if (m_privateCache == null)
            {
                Dictionary <DateTime, T> history = null;
                if (useGlobalCacheForHistory)
                {
                    var obj = m_context.LoadGlobalObject(cashKey, fromStorage);
                    switch (obj)
                    {
                    case Dictionary <DateTime, T> t:
                        history = t;
                        break;

                    case NotClearableContainer <Dictionary <DateTime, T> > t:
                        history = t.Content;
                        break;
                    }

                    if (history == null)
                    {
                        string msg = String.Format("[{0}] GLOBAL history '{1}' not found in global cache for key.GetHashCode: {2}",
                                                   m_context.Runtime.TradeName ?? "EMPTY", cashKey, cashKey.GetHashCode());
                        m_context.Log(msg, MessageType.Info, false);

                        history = new Dictionary <DateTime, T>();
                        var data = new NotClearableContainer <Dictionary <DateTime, T> >(history);
                        m_context.StoreGlobalObject(cashKey, data, fromStorage);
                    }
                }
                else
                {
                    var obj = m_context.LoadObject(cashKey, fromStorage);
                    switch (obj)
                    {
                    case Dictionary <DateTime, T> t:
                        history = t;
                        break;

                    case NotClearableContainer <Dictionary <DateTime, T> > t:
                        history = t.Content;
                        break;
                    }

                    if (history == null)
                    {
                        string msg = String.Format("[{0}] Local history '{1}' not found in local cache for key.GetHashCode: {2}",
                                                   m_context.Runtime.TradeName ?? "EMPTY", cashKey, cashKey.GetHashCode());
                        m_context.Log(msg, MessageType.Info, false);

                        history = new Dictionary <DateTime, T>();
                        var data = new NotClearableContainer <Dictionary <DateTime, T> >(history);
                        m_context.StoreObject(cashKey, data, fromStorage);
                    }
                }

                m_privateCache = history;
            }

            return(m_privateCache);
        }
Example #13
0
        public double Execute(InteractiveSeries profile, int barNum)
        {
            // В данном случае намеренно возвращаю Double.NaN
            double failRes = Double.NaN;

            if (m_repeatLastValue)
            {
                failRes = Double.IsNaN(m_prevValue) ? Double.NaN : m_prevValue; // В данном случае намеренно возвращаю Double.NaN
            }
            Dictionary <DateTime, double> results;

            #region Get cache
            // [2019-01-30] Перевожу на использование NotClearableContainer (PROD-6683)
            string key       = m_variableId + "_results";
            var    container = m_context.LoadObject(key) as NotClearableContainer <Dictionary <DateTime, double> >;
            if (container != null)
            {
                results = container.Content;
            }
            else
            {
                results = m_context.LoadObject(key) as Dictionary <DateTime, double>; // Старая ветка на всякий случай
            }
            if (results == null)
            {
                string msg = String.Format(RM.GetString("OptHandlerMsg.GetValueAtm.CacheNotFound"),
                                           GetType().Name, key.GetHashCode());
                m_context.Log(msg, MessageType.Info);

                results   = new Dictionary <DateTime, double>();
                container = new NotClearableContainer <Dictionary <DateTime, double> >(results);
                m_context.StoreObject(key, container);
            }
            #endregion Get cache

            int len = m_context.BarsCount;
            if (len <= 0)
            {
                return(failRes);
            }

            // Вот так не работает. По всей видимости, это прямая индексация от утра
            //DateTime now = m_context.Runtime.GetBarTime(barNum);

            ISecurity sec = m_context.Runtime.Securities.FirstOrDefault();
            if ((sec == null) || (sec.Bars.Count <= barNum))
            {
                return(failRes);
            }

            DateTime now = sec.Bars[barNum].Date;
            double   rawRes;
            if (results.TryGetValue(now, out rawRes))
            {
                m_prevValue = rawRes;
                return(rawRes);
            }
            else
            {
                int barsCount = ContextBarsCount;
                if (barNum < barsCount - 1)
                {
                    // Если история содержит осмысленное значение, то оно уже содержится в failRes
                    return(failRes);
                }
                else
                {
                    #region Process last bar(s)
                    if (profile == null)
                    {
                        return(failRes);
                    }

                    SmileInfo profInfo = profile.GetTag <SmileInfo>();
                    if ((profInfo == null) || (profInfo.ContinuousFunction == null))
                    {
                        return(failRes);
                    }

                    double f  = profInfo.F;
                    double dT = profInfo.dT;
                    if (Double.IsNaN(f) || (f < Double.Epsilon))
                    {
                        string msg = String.Format(RM.GetString("OptHandlerMsg.FutPxMustBePositive"), GetType().Name, f);
                        m_context.Log(msg, MessageType.Error);
                        return(failRes);
                    }

                    if (!DoubleUtil.IsZero(m_moneyness))
                    {
                        if (Double.IsNaN(dT) || (dT < Double.Epsilon))
                        {
                            string msg = String.Format(RM.GetString("OptHandlerMsg.TimeMustBePositive"), GetType().Name, dT);
                            m_context.Log(msg, MessageType.Error);
                            return(failRes);
                        }
                    }

                    double effectiveF;
                    if (DoubleUtil.IsZero(m_moneyness))
                    {
                        effectiveF = f;
                    }
                    else
                    {
                        effectiveF = f * Math.Exp(m_moneyness * Math.Sqrt(profInfo.dT));
                    }
                    if (profInfo.ContinuousFunction.TryGetValue(effectiveF, out rawRes))
                    {
                        m_prevValue  = rawRes;
                        results[now] = rawRes;
                    }
                    else
                    {
                        rawRes = failRes;
                    }
                    #endregion Process last bar(s)

                    m_result.Value = rawRes;
                    m_context.Log(MsgId + ": " + m_result.Value, MessageType.Info, PrintInLog);

                    return(rawRes);
                }
            }
        }