/// <summary> /// Метод под флаг TemplateTypes.SECURITY, чтобы подключаться к источнику-БА /// </summary> public IList <double> Execute(ISecurity sec) { List <double> historySigmas = m_context.LoadObject(VariableId + "historySigmas") as List <double>; if (historySigmas == null) { historySigmas = new List <double>(); m_context.StoreObject(VariableId + "historySigmas", historySigmas); } int len = sec.Bars.Count; int barLengthInSeconds = (int)sec.IntervalInstance.ToSeconds(); LinkedList <KeyValuePair <DateTime, double> > logs = m_context.LoadObject(VariableId + "logs") as LinkedList <KeyValuePair <DateTime, double> >; if (logs == null) { logs = new LinkedList <KeyValuePair <DateTime, double> >(); m_context.StoreObject(VariableId + "logs", logs); } // Типа, кеширование? for (int j = historySigmas.Count; j < len; j++) { IDataBar bar = sec.Bars[j]; DateTime t = bar.Date; double v = bar.Close; double ln = Math.Log(v); logs.AddLast(new KeyValuePair <DateTime, double>(t, ln)); double hv; if (HV.TryEstimateHv( logs, m_period, barLengthInSeconds, m_annualizingMultiplier, m_useAllData, out hv)) { double vol = hv; historySigmas.Add(vol); } else { historySigmas.Add(Double.NaN); } } return(new ReadOnlyCollection <double>(historySigmas)); }
/// <summary> /// Метод под флаг TemplateTypes.SECURITY, чтобы подключаться к источнику-БА /// </summary> public IList <double> Execute(ISecurity sec) { if (sec == null) { // [{0}] Empty input (security is NULL). string msg = RM.GetStringFormat("OptHandlerMsg.SecurityIsNull", GetType().Name); m_context.Log(msg, MessageType.Warning, true); return(Constants.EmptyListDouble); } Dictionary <DateTime, double> hvSigmas = null; //int barLengthInSeconds = (int)sec.IntervalInstance.ToSeconds(); int barLengthInSeconds = m_timeframe; string cashKey = HV.GetGlobalCashKey(sec.Symbol, false, m_useAllData, barLengthInSeconds, m_annualizingMultiplier, m_period); try { 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>; } } } 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 'hvSigmas' from global cache. cashKey: {2}; Message: {3}\r\n\r\nfName: {4}; path: {5}\r\n\r\n{6}", GetType().Name, nse.GetType().FullName, cashKey, nse.Message, fName, path, nse); m_context.Log(msg, MessageType.Warning, true); } catch (Exception ex) { string msg = String.Format("[{0}.PrepareData] {1} when loading 'hvSigmas' from global cache. cashKey: {2}; Message: {3}\r\n\r\n{4}", GetType().Name, ex.GetType().FullName, cashKey, ex.Message, ex); m_context.Log(msg, MessageType.Warning, true); } if (hvSigmas == null) { // Данного ключа в глобальном кеше нет? Тогда выход. // [{0}.PrepareData] There is no HV in global cache. Probably, you have to start agent 'HV (ALL)' for security '{1}'. string msg = RM.GetStringFormat("OptHandlerMsg.GlobalHv.CacheNotFound", GetType().Name, sec); if (m_context.Runtime.IsAgentMode) { throw new ScriptException(msg); // PROD-4624 - Андрей велит кидать исключение. } // А если в режиме лаборатории, тогда только жалуемся и продолжаем. m_context.Log(msg, MessageType.Warning, true); return(Constants.EmptyListDouble); } List <double> res = new List <double>(); int len = sec.Bars.Count; if (len <= 0) { return(res); } int oldResLen = res.Count; double prevHv = Double.NaN; for (int j = oldResLen; j < len; j++) { DateTime now = sec.Bars[j].Date; double hv; if ((hvSigmas.TryGetValue(now, out hv)) && (!Double.IsNaN(hv)) && (hv > 0)) { prevHv = hv; res.Add(hv); } else { if (m_repeatLastHv) { if (!Double.IsNaN(prevHv)) { hv = prevHv; } else { hv = Constants.NaN; if (j == 0) { #region Отдельно обрабатываю нулевой бар double tmp = Double.NaN; DateTime foundKey = new DateTime(1, 1, 1); // [2016-02-02] Когда история становится слишком длинной, это может вызывать проблемы // при итерировании в foreach. Потому что другой поток может в этот момент добавить новую точку в коллекцию. int repeat = 7; while (repeat > 0) { tmp = Double.NaN; foundKey = new DateTime(1, 1, 1); try { lock (hvSigmas) { foreach (var kvp in hvSigmas) { 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}.Execute] {1} when iterate through 'hvSigmas'. cashKey: {2}; Message: {3}\r\n\r\n{4}", GetType().Name, invOpEx.GetType().FullName, cashKey, invOpEx.Message, invOpEx); m_context.Log(msg, MessageType.Warning, true); throw; } } } if ((foundKey.Year > 1) && (!Double.IsNaN(tmp)) && (tmp > 0)) { hv = tmp; prevHv = hv; } #endregion Отдельно обрабатываю нулевой бар } } res.Add(hv); } else { res.Add(Constants.NaN); } } } return(res); }